关于arm汇编入栈和出栈的总结

来源:互联网 发布:手绘地图软件生成器 编辑:程序博客网 时间:2024/04/30 19:16

用汇编进行函数内压栈和出栈往往使用如下的语句:

 stmfd sp!, {r0-r9, lr} ; (1)给寄存器r0-r9, lr压栈

 ldmfd sp!, {r0-r9, pc}; (2)给寄存器r0-r9出栈, 并使程序跳转回函数的调用点

 

stmfd  代表满递减入栈,即sp指向栈顶元素,每入栈一个元素,sp的值减4;

ldmfd  代表的是满递减出栈,正确的含义是sp指向栈顶元素,每出栈一个元素,sp值加4。

 

用TRACE32做实验可得下面的结果。

执行(1)之前的寄存器情况如下图:

 

                                     图1

 

R13的值为0x5801FFE8, 保存11个寄存器,则入栈后地址应该是0x5801FFE8-11*4=0x

5801FFBC

单步执行过(1)指令后,寄存器的情况如下图:

 

                                     图2

注意R13 已经变成了0x5801FFBC.

再来看出栈后寄存器的情况,如下图:

 

                                     图3

出栈以后R13值变回0x5801FFE8

所以我们可以知道ldmfd 事实上是递增的。 TRACE32可以看到stmfdldmfd这两个助记符对应的汇编指令,如下图:

 

                                                                          图4

stmfd 对应的汇编指令,实际上是stmdb

 

ldmfd对应的汇编指令,实际上是ldmia

 

另外如果您认为入栈的顺序是从r0开始到r9再到lr您就错了。真正的顺序是正好相反的。这一点您可以观察图2看到寄存器入栈的真实顺序,r0的值0x08005000是位于栈顶的。

 

总结一下:

stmfd和ldmfd是配对使用的,stmfd=stmdb, ldmfd=ldmia

在“{}”中括着的寄存器的入栈顺序是从后向前,出栈顺序是从前向后。

 

原创粉丝点击