You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

x86 Heaven's Gate技术在ARM架构上的等效实现方法

ARM架构同进程混合运行32位与64位代码的实现方式

ARM架构(ARMv8及后续支持64位的版本)的执行状态切换逻辑和x86有本质区别,你没法像x86那样靠跨段远调用在用户态直接完成32/64位状态切换,具体规则和落地方法如下:

  • 先讲底层硬件逻辑:ARMv8定义了两套完全独立的执行态,分别是跑ARM64指令集的AArch64(64位)、跑A32/Thumb指令集的AArch32(32位)。两种状态下的寄存器模型、寻址范围、栈帧规则、系统调用表全不兼容。和x86靠代码段描述符标志位控制执行态的设计不一样,ARM的执行状态由PSTATE寄存器的特权位nRW控制,这个位只能在内核态(EL1及以上异常级别)修改,用户态没有直接写的权限,普通的跳转、调用指令根本碰不到这个位,自然没法直接切态。
  • 所有跨32/64位的状态切换必须由内核参与完成,硬件唯一支持的用户态跨态入口是异常返回(ERET)路径:内核在处理系统调用、异常、信号返回的时候,会根据之前保存的SPSR(程序状态保存寄存器)里的nRW位值,决定返回用户态之后进AArch64还是AArch32跑。
  • 以Linux系统为例,实际工程里能落地的混跑方案,都是靠信号返回机制实现跨态切换,操作步骤很明确:
    1. 进程随便以哪种状态启动都行,比如先跑AArch64,只要内核给进程开了双态兼容权限就可以。
    2. 提前把要跑的异态代码(比如32位代码)、给异态用的栈、相关数据都映射到进程虚拟地址的低4GB范围里——AArch32态只能寻址32位地址空间,不在0~4GB范围内的内存它根本访问不到。
    3. 需要切到异态执行的时候,手动构造对应格式的信号返回帧,在帧里的SPSR字段设好目标执行态的标志位,把返回PC改成异态代码的入口地址,配好异态要用的栈指针、传参寄存器,最后调用rt_sigreturn进内核,内核做完合法性校验之后,就会按你设置的状态返回用户态,直接开始跑异态代码。
    4. 异态代码跑完要切回原状态的时候,重复一遍构造信号帧、调sigreturn的流程就行。
  • 几个必须注意的坑:
    • 跨态的时候硬件不会自动帮你转上下文,你得自己按两套架构的传参规则手动处理参数:AArch64用X0X7传参,栈要16字节对齐;AArch32用R0R3传参,栈8字节对齐就行。
    • 不少ARM处理器从硬件上就砍了AArch32支持,比如Apple M系列芯片、部分服务器级Cortex核心,这类硬件上根本跑不了32位ARM代码,别想混跑的事。
    • 部分系统从软件层面禁了AArch32,比如新版macOS、iOS,就算硬件支持也跑不了32位程序。
  • 两种架构的实现差异可以直接看代码对比,区别非常明显:
; x86方案:用户态直接靠远调用切态,完全不需要内核参与
BITS 32
; 执行32位逻辑
call 0x33:foo  ; 跨段远调用直接切到64位
; 继续跑32位逻辑

BITS 64
foo:
; 执行64位逻辑
retf  ; 远返回直接切回32位
// ARM方案:必须通过内核的信号返回路径切态,没有用户态直接切换的可能
// 以下是AArch64态切到AArch32的简化逻辑示意
// 1. 提前把32位代码、32位栈映射到低4G地址区间
// 2. 构造rt_sigreturn帧:设置SPSR.nRW=AArch32,PC=a32_entry,SP=分配好的32位栈顶
// 3. 调用rt_sigreturn进入内核,由内核完成状态切换
// ... 内核返回后就进入AArch32态开始执行
a32_entry:
  // 执行32位业务逻辑
  // 要切回64位时,重复构造信号帧的流程,调用sigreturn切回即可

别尝试在用户态直接写PSTATE寄存器改执行态,这类操作会直接触发权限异常,进程当场崩溃。

内容的提问来源于stack exchange,提问作者Joseph Sible-Reinstate Monica

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.28 12:09:22