假设代码段.text首地址为0x8054
错误的代码示例:
.text
.code 32
.global _start
_start:
bl main @1. pc = 0x8054,lr = 0x0
b .
main:
push {lr} @2. pc = 0x805c,lr = 0x8058
bl func1 @3. pc = 0x8060,lr = 0x8058 @栈1
pop {pc} @
func1:
bl func2 @4. pc = 0x8068,lr = 0x8064
mov pc, lr @6. pc = 0x806c,lr = 0x806c @程序在此死循环,回不去主函数
func2:
mov pc, lr @5. pc = 0x8070,lr = 0x806c
修正后:
.text
.code 32
.global _start
_start:
bl main @1. pc = 0x8054,lr = 0x0
b . @9. pc = 0x8058,lc = 0x8070 @栈空
main:
push {lr} @2. pc = 0x805c,lr = 0x8058
bl func1 @3. pc = 0x8060,lr = 0x8058 @栈1
pop {pc} @8. pc = 0x8064,lr = 0x8070 @栈3
func1:
push {lr} @4. pc = 0x8068,lr = 0x8064
bl func2 @5. pc = 0x806c,lr = 0x8064 @栈2
pop {pc} @7. pc = 0x8070,lr = 0x8070
func2:
mov pc, lr @6. pc = 0x8074,lr = 0x8070
两个程序的区别在于func1中有没有对lr寄存器进行压栈备份,由于前者没有备份,所以程序在连续跳转时丢失了回去的路。
因此在跳转指令bl被嵌套使用时,应该对lr寄存器进行压栈备份,在最后一层嵌套中使用mov pc, lr指令返回主调函数,然后逐层pop最终回到主函数.