如何将给定ARM64汇编代码转换为32位架构ARM汇编适配树莓派
ARM64汇编转32位树莓派ARM汇编指导
前置核心差异说明
- 32位ARM(ARMv7-A架构,树莓派32位系统通用架构)通用寄存器为
r0~r15,无ARM64的x0~x31类64位寄存器:r11对应帧指针fp(等效ARM64的x29),r14为链接寄存器lr(等效x30),r13为栈指针sp - 32位ARM无
stp/ldp成对读写寄存器指令,需单独用str/ldr操作 - 32位ARM无专用零寄存器,要写入0值需先给通用寄存器赋值
#0再存储 - 32位ARM小地址重定位无需
lo12:前缀
逐行转换对应
原ARM64代码片段
stp x29, x30, [sp, -48]! mov x29, sp str wzr, [sp, 44] bl __isoc99_scanf add x0, x0, :lo12:.LC1 //.LC1 is a function
每行转换逻辑
- 原第一行
stp x29, x30, [sp, -48]!:先分配48字节栈空间,再分别存储帧指针和链接寄存器
对应32位代码:@ 分配48字节栈空间(ARM32为满递减栈) sub sp, sp, #48 @ 保存r11(fp)、r14(lr)到栈底 str r11, [sp, #0] str r14, [sp, #4] - 原第二行
mov x29, sp:赋值帧指针
对应32位代码:mov r11, sp - 原第三行
str wzr, [sp, 44]:给栈偏移44的位置写0
对应32位代码:mov r0, #0 str r0, [sp, #44] - 原第四行
bl __isoc99_scanf:函数调用指令逻辑一致,树莓派Linux glibc环境下函数名通用
对应32位代码:bl __isoc99_scanf - 原第五行
add x0, x0, :lo12:.LC1:加载.LC1地址,无需lo12标记,汇编器报错可改用ldr伪指令
对应32位代码:add r0, r0, #.LC1 @ 汇编报错时替换为下面的伪指令: @ ldr r0, =.LC1
完整转换后的32位汇编片段
@ 栈初始化+上下文保存 sub sp, sp, #48 str r11, [sp, #0] str lr, [sp, #4] mov r11, sp @ 栈偏移44位置写0 mov r0, #0 str r0, [sp, #44] @ 调用scanf bl __isoc99_scanf @ 加载LC1地址到r0 add r0, r0, #.LC1
额外注意事项
- 32位ARM函数调用约定(AAPCS)和ARM64不同,前4个参数通过
r0~r3传递,超出部分压栈,若原代码有参数传递逻辑需对应调整 - 树莓派32位系统默认支持ARM/Thumb两种指令集,用Thumb指令集时需要在代码开头添加
.thumb伪指令 - 32位ARM栈空间要求至少4字节对齐,部分系统调用、函数调用场景要求8字节对齐,分配栈空间时需满足对齐要求
内容的提问来源于stack exchange,提问作者MaciG
相关产品推荐
相关产品推荐

