Skip to content
On this page

ARM汇编_栈操作指令


标签:ARM32汇编/指令  

栈的类型

  • 增栈:压栈之后,栈指针向高地址方向移动
  • 减栈:压栈之后,栈指针向低地址方向移动
  • 空栈:栈指针指向的是最后一次压入到栈中的数据相邻的内存空间,所以再压栈的时候可以直接压栈在移动指针
  • 满栈:栈指针指向的是最后一次压入到栈中的数据,再压栈的时候需要先移动指针后压栈
  • 所以栈可以分为满增(FA)/满减(FD)/空增(EA)/空减(ED)四类
  • ARM 使用满减栈:先移动有压栈,向低地址移动

满减栈的实现

  1. 可以使用多寄存器读写的方式实现满减栈
asm
mov r1,#1 
mov r2,#2 
mov r3,#3 
mov r4,#4 
mov r5,#5 
LDR r11,=0x40000800 
stmdb r11!,{r1-r5} 
ldmia r11!,{r6-r10}
  1. 可以采用 fd 后缀实现满减栈
asm
mov r1,#1 
mov r2,#2 
mov r3,#3 
mov r4,#4 
mov r5,#5 
LDR sp,=0x40000800 
stmfd sp!,{r1-r5} 
ldmfd sp!,{r6-r10}

利用栈的函数调用

  1. 叶子函数调用过程
asm
.text  
.global start 

_start: 
@初始化栈
  LDR sp,=0X40000800 
  b main
main: 
  mov r1,#1 
  mov r2,#2 
  bl func
  add r3,r1,r2
  b main
 
func: 
  @压栈保护现场
  stmfd sp!,{r1,r2} 
  mov r1,#3 
  mov r2,#4 
  sub r4,r2,r1
  @出栈恢复现场
  ldmfd sp!,{r1,r2} 
  mov pc,lr

.end
  • 每次的函数调用通过压栈备份寄存器 r1r2 的数据,等函数运行完毕,再通过弹栈把数据读回 r1r2
  1. 非叶子函数调用过程
asm
.text  
.global start 

_start: 
@初始化栈
  LDR sp,=0X40000800 
  b main
main: 
  mov r1,#1 
  mov r2,#2 
  bl func
  add r3,r1,r2
  b main
 
func: 
  @压栈保护现场
  stmfd sp!,{r1,r2,lr} 
  mov r1,#3 
  mov r2,#4 
  bl fun 
  sub r4,r2,r1
  @出栈恢复现场
  ldmfd sp!,{r1,r2,lr} 
  mov pc,lr

fun: 
  @压栈保护现场
  stmfd sp!,{r1,r2} 
  mov r1,#5 
  mov r2,#6 
  add r5,r1,r2
  @出栈恢复现场
  ldmfd sp!,{r1,r2} 
  mov pc,lr

.end
  • 上面代码中的 func 是一个非叶子函数,它的区别在于压栈的时候保存了 lr 寄存器的数据,如果不保存 lr 的话,当它调用 fun 后,lr 的数据就被改变了,func 就无法回到 main 函数

Last updated: