- UID
- 1
- 精华
- 积分
- 76365
- 威望
- 点
- 宅币
- 个
- 贡献
- 次
- 宅之契约
- 份
- 最后登录
- 1970-1-1
- 在线时间
- 小时
|
ARM的寄存器:
r0,r1,r2,r3,r4,r5,r6,r7,r8,r9,r10,r11,r12,r13,r14,r15
看图。
r0到r3,还有r12是常用寄存器。其中r0到r3被用于函数传参,r12则是被拿来随便用,所以子过程不保证返回后它的值不变。
r0也被用于传函数返回值。
r4到r11是保留寄存器。用之前入栈,用完了出栈。
r13是栈顶,也写作sp。其实并不怎么在栈上用。
r14是链接寄存器,写作lr,它存储了程序返回的地址。
r15是指令计数器,写作pc,用于读指令。
ARM汇编与x86汇编之间做个对比:
- 都有栈顶寄存器。
- ARM多了个链接寄存器,用于返回。
这一点和x86不同。x86用call来调用函数,这个过程会把返回地址压入栈,然后转到被调用的函数的入口。被调用的函数执行完了后,再用ret来返回。x86的ret从栈顶弹出返回地址到指令指针,从而返回到调用者。
而ARM的调用则是使用bl或者blx指令,它把返回地址存到链接寄存器lr,然后修改指令计数器pc。此处有个疑问:如果被调用的函数也要调用函数的话,怎么办?答案是:把链接寄存器lr入栈。这样lr就可以被嵌套使用了。而且你还可以用pop指令把栈顶上的返回地址弹出到pc上来返回,或者“返返回”,回到调用者的调用者那里去。
调用指令“bl”全名“branch with link”,“带链接的分支”。而不带链接的分支,则是“B”,跳转指令。也就是“branch”的缩写。 - x86使用“指令指针寄存器”eip,去“代表”执行的指令的地址。而ARM则使用“指令计数器”pc。这个pc有个特性,在后面我会说一下。
ARM的PC寄存器并不指向当前执行的指令的地址,而是指向当前执行的指令的下下一条指令的地址。
为啥要这样设计呢?因为ARM它有个三级流水线。
- 从[PC]处取出指令。
- 把取出的指令进行译码,也就是判断它是一条干啥的指令。
- 知道这条指令是干啥的了以后,再执行。
ARM它并不傻乎乎地取一条执行一条。它三件事是同时执行的。每个周期,它都从[PC]处取指,并且把上一个周期取到的指令进行译码,并且执行上上一个周期译码完成的指令。
(PS:我不是在说51单片机傻)
因为这个关系,ARM的PC总是指向当前执行的指令的下下一条。也就是它正在取指的地方。就是这个地方,ARM的pc和x86的eip不同。
当ARM执行了一条跳转指令后,它就得清空这个流水线,丢掉之前取到的指令,然后重新取新的。这会导致ARM处理器不得不先懵逼两个周期,然后在第三个周期才能开始执行。所以从优化上来说,要尽量减少跳转。
参考资料:
https://community.arm.com/proces ... -from-arm-assembler
http://m.blog.csdn.net/abclixu123/article/details/7471822
PS.感谢coldzenleft给我的帮助
|
|