入栈
&a表示a的地址。
Push {r3,lr}
lr即R14。SP = SP-4,lr入栈;SP = SP-4,r3再入栈。
Push {R0,R1}
栈的高地址在上,低地址在下。R13(SP)为栈指针。高标号的寄存器在栈的高地址,如Rn在高地址,Rn-1在低地址。Push{R0,R1}相当于执行多次STR和调整SP。R1在高地址,R0在低地址,SP的值依次减少4,完成入栈过程。
出栈
先进后出。栈顶位于“低地址”,在下面。R0 = [SP], SP = SP+4; R1 = [SP], SP = SP+4.出栈时会向上“增长”,恢复原先的值。
POP {r3, pc}分为以下两个步骤。
r3 = [SP], SP = SP+4;
即r3等于SP所指示的值。
pc = [SP], SP = SP+4.
pc,即程序计数器。
实例分析
原C程序
汇编码
main函数从PUSH {r2-r3,lr}处开始执行。
操作A:SP = SP - 4,lr(即R14)入栈;SP = SP - 4,r3入栈;SP = SP - 4,r2入栈。
操作B:r0赋值1,将r0的值存储在sp+4的位置。该操作即为int a = 1.
操作C:r0赋值2,将r0的值存储在sp的位置。该操作即为int b = 2.
r1 = sp = &b,r0 = sp + 4 = &a, lr记录return 0的地址(即lr = 0x0800015E),跳转至0x08000138执行add_val()函数。即add_val(r0, r1).
SP = SP - 4,lr(即R14)入栈;SP = SP - 4,r3入栈。
从r0+0(SP,这里是指之前的SP + 4)所表示地址的内存中读取到r2中,即r2 = [r0 + 0] = [&a] = 1.再将r2的值(1)存储在SP + 0表示的地址的值中(即SP目前所指示的位置,r3)。
从r1+0(SP,这里是指之前的SP)所表示地址的内存中读取到r2中,即r2 = [r1 + 0] = [&b] = 2.再从SP + 0所表示地址的内存中(1)读取到r3中,计算r2 = r2 + r3,再将r2的值(3)存储在SP + 0表示的地址的值中。
从SP + 0所表示地址的内存中读取到r2,再将r2的值(3)存储在r0 + 0表示的地址(SP + 4)的值中(即把2写入SP + 4这个位置)。即r2 = [SP + 0] = temp = 3,r2的值(3)写入[r0 + 0] = [&a].
此时,add_val()函数执行完成。要返回return 0.
执行POP {r3,pc}.即r3 = [SP] = 3, SP = SP + 4,PC = [SP] = 0x0800015E, SP = SP + 4.