ARM汇编之栈

创建进程的时候,会分配内存作为栈。
实际栈指令(push,pop)是其他指令的别名,实际指令是STR、LDR或者其延伸指令。例STMDB sp,{R0,R1}== push {r0, r1}

栈实现的几种情况
堆栈类型storeload
完全下降(高地址在上,低地址在下)STMFD(STMDB)LDMFD(LDM)
完全升序(高地址在下,低地址在上)STMFA (STMIB)LDMFA (LDMDA)
空升序(高地址在下,低地址在上)STMEA (STM)LDMEA (LDMDB)
空降序(高地址在上,低地址在下)STMED (STMDA)LDMED (LDMIB)

总结:

  • 升序A:高地址在下,低地址在上
  • 降序D:高地址在上,低地址在下
  • 完全F:入栈的时候:SP先减4,然后在写数据。出栈的时候:先写数据再执行SP+4
  • 空E:入栈的时候:先写数据,然后再SP减4。出栈的时候:先执行SP+4再写数据

基础姿势:栈操作

返回地址LR:当前函数执行完,跳转的下一条指令,通常是call当前函数所在地址的下一条地址。例如,下面的代码中:当执行进son_add函数中时,返回地址就是int c=10;这条指令的地址,确保执行完son_add函数后,返回到父函数father中继续执行流程,调用后面的代码。也就是数返回地址保证的是每一个函数块间的指令流程

PC:程序计数器,通常指向下一条指令的地址。例如:当前程序执行到了int a=8;,当处理器编译这条指令的时候,PC所存储的值,就是int b = 9;这条指令的内存地址,也就是PC寄存器保证的是每一条指令间的指令流程

栈帧(r11):函数调用的时候,会在栈中进行,每一个函数执行过程就是一个栈帧

帧指针: 栈帧首地址的内存地址。也就是返回地址的内存地址

int son_add(int a, int b)
{
        return a+b;
}
int father()
{
        int a = 8;
        int b = 9;
        int sum = 0;
        sum = son_add(a, b);
        int c=10;
        return sum;
}

栈帧结构:下面这个图可以适用于上面代码中的fahter函数,如果是son_add的栈帧,只需要减少一步:返回地址的入栈操作,为什么会少这一步呢?首先需要知道:lr只表示当前函数的返回地址,如果当前函数有子函数,进入子函数lr就需要保存子函数的返回地址,但是父函数的返回地址就会被覆盖,所以需要先存起来,等子函数执行完成返回到父函数执行流程中,重新将返回地址存入lr中即可。因为上面的子函数内部不需要调用函数,所以不存在覆盖情况,就只用lr即可。

13671484-39d4ecda18b18001.png

函数栈调用的详细分析

  • 当函数传入的参数超过4个时,需要用到堆栈存储其余参数
  • r0来保存返回结果
  • 当返回结果超过32位,就需要用r0和r1结合来保存结果
/* azeria@labs:~$ gcc func.c -o func && gdb func */
int main()
{
 int res = 0;
 int a = 1;
 int b = 2;
 res = max(a, b);
 return res;
}

int max(int a,int b)
{
 do_nothing();
 if(a<b)
 {
 return b;
 }
 else
 {
 return a;
 }
}
int do_nothing()
{
 return 0;
}
序幕:为函数设置环境、
push   {r11, lr}    /* 序幕开始:保存帧指针和返回地址到堆栈*/
add    r11, sp, #0  /* 设置当前栈帧的帧指针,指向栈帧的头部地址,即返回地址的地址 */
sub    sp, sp, #16  /* 序幕结束:会根据参数和局部变量分配相应的堆栈空间 */
函数的正文:实现函数的逻辑,并将返回结果赋值给r0
mov    r0, #1       /*传入参数 */
mov    r1, #2       /*传入参数 */
bl     max     
结尾:恢复到初始状态,以便从父函数离开的地方继续执行
sub    sp, r11, #0  /* 调整栈指针 */
pop    {r11, pc} /* 恢复帧指针,并将返回地址放入pc中,实现直接跳转到返回地址处。在此步骤中,栈帧会被销毁 */
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值