原函数
int add(volatile int a, volatile int b) {
volatile int sum;
sum = a + b;
return sum;
}
反汇编
PUSH {r0, rl, lr}
SUB sp, sp, #4
LDR r0, rl, [sp, #4]
ADD r0, r0, rl
STR r0, [sp, #0]
POP {r1-r3, pc}
PUSH {r0, rl, lr}
:此指令将寄存器r0
,rl
和lr
的值推入堆栈。SUB sp, sp, #4
:此指令从堆栈指针(sp
)中减去4
,实际上在堆栈上分配了4字节的空间。LDR r0, rl, [sp, #4]
:此指令将通过将4
加到sp
所计算出的内存地址的值加载到寄存器r0
和rl
中。ADD r0, r0, rl
:此指令将r0
和rl
的值相加,并将结果存储在r0
中。STR r0, [sp, #0]
:此指令将r0
的值存储在由sp
指向的内存地址中。POP {r1-r3, pc}
:此指令从堆栈中弹出值到寄存器r1
到r3
和程序计数器(pc
),实际上是从函数返回。
r0 = 1
rl = 2
(假设这是一个合法的寄存器,虽然在标准的ARM架构中并不存在rl
寄存器)lr = 3
sp = 0x100
(假设我们的堆栈从内存地址0x100
开始)
初始堆栈状态:
_____ | | <- Stack Pointer (SP) |_____| | | |_____| | | |_____|
PUSH {r0, rl, lr}
: 把r0
,rl
,lr
的值压入堆栈,堆栈指针sp
下移。
_____ | 3 | |_____| <- Stack Pointer (SP) | 2 | |_____| | 1 | |_____|
2.SUB sp, sp, #4
:栈指针下移4字节,为新数据分配空间。
_____ | | <- Stack Pointer (SP) |_____| | 3 | |_____| | 2 | |_____| | 1 | |_____|
3.LDR r0, rl, [sp, #4]
:从 sp+4
的内存位置加载值到 r0
和 rl
寄存器。在这里,r0
和 rl
的值变为 3
。
4.ADD r0, r0, rl
:将 r0
和 rl
的值相加,结果存入 r0
,所以 r0
变为 6
。
5.STR r0, [sp, #0]
:将 r0
的值存入 sp+0
的内存位置。因此,栈顶的值变为 6
。
_____ | 6 | <- Stack Pointer (SP) |_____| | 3 | |_____| | 2 | |_____| | 1 | |_____|
6.POP {r1-r3, pc}
:从堆栈中弹出值到 r1
, r2
, r3
和 pc
。在这里,我们假设之后的内存位置是空的,所以这些寄存器的值都变为 0
,并且 sp
的值变为原来的位置。
_____ | | <- Stack Pointer (SP) |_____| | | |_____| | | |_____|