简介
ARM相关,以下所有汇编皆基于armv7
寄存器
- 总数:37
- r0: 存储函数参数与返回值
- r1: 存储函数参数与返回值
- r2: 存储函数参数与返回值
- r3: 存储函数参数与返回值
- r4: 存储局部变量
- r5: 存储局部变量
- r6: 存储局部变量
- r7: 存储局部变量
- r8: 存储局部变量(仅arm模式)
- r9: 存储局部变量(仅arm模式)
- r10: 存储局部变量(仅arm模式)
- r11: 存储局部变量(仅arm模式)
- r12: 存储ip
- r13: 存储sp
- r14: 存储lr
- r15: 存储pc
- cpsr[31]:n(negative)
- cpsr[30]😒(zero)
- cpsr[29]:c(carry)
- cpsr[28]:v(overflow)
- cpsr[27]:保留位
- cpsr[26]:保留位
- cpsr[25]:保留位
- cpsr[24]:保留位
- cpsr[23]:保留位
- cpsr[22]:保留位
- cpsr[21]:保留位
- cpsr[20]:保留位
- cpsr[19]:保留位
- cpsr[18]:保留位
- cpsr[17]:保留位
- cpsr[16]:保留位
- cpsr[15]:保留位
- cpsr[14]:保留位
- cpsr[13]:保留位
- cpsr[12]:保留位
- cpsr[11]:保留位
- cpsr[10]:保留位
- cpsr[9]: 保留位
- cpsr[8]: 保留位
- cpsr[7]:存储IRQ中断禁止位 1:禁止,0:允许
- cpsr[6]:存储FIQ中断禁止位 1:禁止,0:允许
- cpsr[5]:存储工作状态位 0:arm,1:thumb
- cpsr[4,3,2,1,0]:0b10000(用户user)
- cpsr[4,3,2,1,0]:0b10001(fiq)
- cpsr[4,3,2,1,0]:0b10010(irq)
- cpsr[4,3,2,1,0]:0b10011(管理svc)
- cpsr[4,3,2,1,0]:0b10111(中止abort)
- cpsr[4,3,2,1,0]:0b11011(未定义und)
- cpsr[4,3,2,1,0]:0b11111(系统sys)
- spsr(fiq):存储中断前cpsr
- spsr(svc):存储中断前cpsr
- spsr(abt):存储中断前cpsr
- spsr(irq):存储中断前cpsr
- spsr(und):存储中断前cpsr
栈
堆
栈平衡
参数只能存放于r0-r3寄存器里,其余的从右往左依次压入栈上,并且由被调用者
执行出栈操作,实现栈平衡,参数存放顺序如下:
[r0:arg0][r1:arg1][r2:arg2][r3:arg3][sp:arg4][sp+4:arg5][sp+8:arg6]
当然这只是一种约定,并不一定非得这样
PUSH与POP
push {r4,r5,r6,lr}
其实相当于
sub sp,sp,#16 ;16=4*4
str lr,[sp, #12]
str r6,[sp, #8]
str r5,[sp, #4]
str r4,[sp, #0]
POP就是与PUSH相反操作即可
指令解析
EOR.W R3, R3, R3,LSR#6
对应c伪代码
r3=r3^(r3>>6)
str r3, [r2, r1, lsl #2]
ldr r3, [r2, r1, lsl #2]
对应c伪代码
r2[r1]=r3;//r2为32位整型数组
r3=r2[r1];
这里的汇编会有<<2操作,是因为整形占4字节,<<2也就是*4,c里面的索引是按整形来数的,而汇编里是按字节来数的,所以需要*4
指令分段
c里面各种语句可以分为几大类:变量定义,赋值,函数调用,所以可以在汇编找ldr,str,b等指令,根据这些指令进行分段,每段相当于c里一条语句
求余运算
汇编里的求余运算根据数值不同,五花八门,比如下面这个例子:
指令优化
gcc在进行编译时,会进行各种复杂的优化,以提升执行效率,具体各种优化请参考:Here
- 函数内联
- 指令段交叉
最后一步str赋值会穿插到下一段指令中
- 循环展开
STR与LDR
- 参考:https://blog.csdn.net/wh8_2011/article/details/53130932
LDM与STM
详细参考:Here
其他指令
- UXTB 参考:HERE
辅助工具
- 代码即时编译工具:https://godbolt.org/
- 代码即时运行调试工具:https://github.com/linouxis9/ARMStrong