首页
社区
课程
招聘
[原创]ARMv7a汇编
发表于: 2025-7-20 22:28 3224

[原创]ARMv7a汇编

2025-7-20 22:28
3224

目标:这是一篇Arm汇编学习笔记,也相当于一份guide,提供了快速了解Arm汇编的“接口”

一、寄存器

二、指令集

三、过程调用规范


通用寄存器(32-bit)

别名/过程调用规范中作用

R0-R3

参数传递/结果返回(调用者保存)

R4-R8

(被调用者保存)

R9

平台寄存器(可变用途)

R10

(被调用者保存)

R11

FP,栈帧指针寄存器,记录当前栈帧基址

(被调用者保存)

R12

IP,内部过程调用临时寄存器

R13

SP,栈指针,指向栈顶,任何函数的出入口处,需满足8字节对齐,即SP mod 8 = 0,即SP mod 0x08 = 0

R14

LR,链接寄存器,保存函数返回地址

R15

PC,程序计数器

其他寄存器

CPSR

当前程序状态寄存器,重点位:N(负数)、Z(零)、C(进位)、V(溢出)、T(处理器指令集,如thumb、arm)

总结:

1、15个通用32位寄存器

2、R4-R11,被调用者保存。即,子函数被调用时,需保存这些寄存器的值,在返回父函数时,恢复这些寄存器的值。R9比较特殊,保留平台相关的配置,有时候有用有时候不用,可直接按被调用者保存处理。

3、R11,FP栈帧指针。一般指向调用函数的FP,形成调用链,可用于栈回溯。实际使用中最常用是用来寻址栈中的数据,因为SP会频繁改变,但FP不会

4、R12,IP寄存器,常用来寻址外部导入函数。比如调用printf,会用来计算printf的地址。

5、LR,不是非易变寄存器,被调用者可以改变,而不恢复,只需要在返回调用者的时候,将LR POP到PC就行。所以可以把LR保存到堆栈,最后从堆栈 POP 到PC

6、CPSR,T标志位控制处理器指令集,如T32(thumb模式)或者A32(arm模式)。A32为定长4字节指令,T32为2字节或4字节指令。NZCV条件标志位

其他(不多BB了解不多):

系统寄存器

浮点寄存器(SX为32个单精度(32-bit)寄存器,DX为16个双精度(64-bit)寄存器),S0-S15参数传递/调用者保存,S16-S31被调用者保存。D0-D7双精度参数传递,D8-D15双精度,被调用者保存。

常用指令:

数据处理

基本运算

ADD(ADR、ADRL),SUB、RSB

逻辑运算

AND(TST)、BIC、ORR、EOR(TEQ)

位操作

LSL、LSR、ASR、ROR

标志位设置

CMN、CMP

内存操作

访存

LDR、STR

块访存

LDMFD、LDMIA、STMFD、STMIA、STMDB、PUSH、POP

分支与跳转

B、BL、BX、BLX;CBZ、CBNZ、TBB、TBH

系统与协处理器指令

系统调用

SVC(触发软中断)、HVC(虚拟化调用)

协处理器操作

MCR/MRC访问协处理器

条件码:

1、A32(arm模式)和T32(thumb模式),A32定长4字节指令,T32为2字节指令与4字节指令混合。

2、数据处理指令,同样的运算方式,一般会有三种指令变体。如下面三条指令,执行的都是加法运算:

ADD(只存放结果,不影响标志位)

ADDS(既存放结果,又影响标志位)

CMN(只影响标志位,不存放结果)

同理,还有SUB、SUBS、CMP;AND、TST;EOR(TEQ)

3、由于A32指令定长4字节,所以无法容纳32位立即数,一般会使用立即数扩展。

MOV指令立即数扩展:A32ExpandImm,imm12,将12位立即数扩展为32位,运算过程是后8位循环右移前4位的值*2

或者使用

可得到:R0 = 0x12345678

4、ADR、ADRL

ADR一般用于寻址计算,实现PC偏移寻址。

如下图main函数调用libc中printf函数。

(off_1654 - 0x1508)可看作printf存储地址与PC之间的偏移offset,ADR指令将PC加上,得到printf的地址。加载前后,offset是不变的,PC加载前0x508加载后变为实际运行时候的指令地址0xB6FF8508,使得通过PC寻址的printf的地址发生改变为0xB6FF9654,如此寻到的printf地址才是正确的地址。

R12之前说过,常用来寻址外部导入函数。如printf函数的调用,由于arm和thumb的BL指令无法寻址完整的32位地址空间,如无法BL 0x12345678,此处则通过ADR、LDR指令来计算地址并加载到PC实现跳转。这段代码通常称为veneer,特点是,一般不改变除r12寄存器和状态寄存器之外的寄存器。

5、其他

RSB R0,R1,#8  =>  R0=8-R1

BIC R0,R1,#8  =>  清除R1的第3位,结果存入R0

6、访存:

将偏移量与从基址寄存器获取的地址相加,结果作为内存访问的地址,并回写到基址寄存器R1。

从基址寄存器获取的地址,不做任何修改,作为内存访问的地址。将偏移量与该地址相加,然后回写到基址寄存器R1。

注意:Arm是满减栈。如下图假如是一个栈帧结构。

“满”意味着SP指针总指向栈顶最后一个元素,图中是0x222,SP的值即位0x00000ff8。

“减“意味着栈的生长方向是向内存地址减小的方向。当放入一个元素,会往低地址放。如STR R0,[SP,#-4]!,则会将R0的值存入SP-4的位置即0x0000ff4处,然后将SP-4写回SP。

7、块访存:
LDMFD、STMFD、LDMIA、STMIA

IA


传播安全知识、拓宽行业人脉——看雪讲师团队等你加入!

收藏
免费 0
支持
分享
最新回复 (1)
雪    币: 42
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
2
可以私聊吗
2025-8-3 22:11
0
游客
登录 | 注册 方可回帖
返回