目的:能分析ARM芯片的汇编代码
学习方法:分析keil软件中的反汇编代码
volatile---是为了防止编译器优化。我把优化等级变成了0还是没有用,因此我直接使用了volatile
1: 压栈和出栈指令
我们通常会在 A 函数中调用 B 函数,当 B 函数执行完以后再回到 A 函数继续执行。要想在跳回 A 函数以后代码能够接着正常运行,那就必须在跳到 B 函数之前将当前处理器状态保存起来(就是保存 R0~R15 这些寄存器值),当 B 函数执行完成以后再用前面保存的寄存器值恢复R0~R15 即可。保存 R0~R15 寄存器的操作就叫做现场保护,恢复 R0~R15 寄存器的操作就叫做恢复现场。
在进行现场保护的时候需要进行压栈(入栈)操作,恢复现场就要进行出栈操作。压栈的指令为 PUSH,出栈的指令为 POP,PUSH 和 POP 是一种多存储和多加载指令,即可以一次操作多个寄存器数据,他们利用当前的栈指针 SP 来生成地址,
PUSH: 将寄存器列表存入栈中。
POP:从栈中恢复寄存器列表。
如我们现在要将 R0~R3 和 R12 这 5 个寄存器压栈,假设当前的 SP 指针指向 0X80000000,处理器的堆栈是向下增长的,使用的汇编代码如下:
PUSH {R0~R3, R12} @将 R0~R3 和 R12 压栈
压栈完成以后的堆栈如图所示:
ARM的栈属于满减栈类型的,高数值的寄存器先进去,低数值的寄存器后进去
拓展知识点:区分SP和PC的值区别,SP指向的是当前栈空间的位置(RAM),PC指向的是下一条运行的指令地址(ROM)
指令 | 描述 |
---|---|
LDR Rd, [Rn , #offset] | 从存储器 Rn+offset 的位置读取数据存放到 Rd 中。 |
STR Rd, [Rn, #offset] | 将 Rd 中的数据写入到存储器中的 Rn+offset 位置。 |
此时R3储存的是i的值,PUSH压进去的R3就是i的存储空间
理解PUSH,STR,LDR的作用即可