Linux函数栈帧
汇编基础
寄存器
rax(accumulator):return value
rbx(base)
rcx(count):4st argument
rdx(data):3st argument
rsi(source index):2st argument
rdi(destination index):1st argument
rbp(base pointer)
rsp(stack pointer)
r8:5st argument
r9:6st argument
r10-r15
rip(instruction pointer)
指令
call指令
相当于执行以下指令:
push %rip
jmp
ret指令
相当于执行以下指令:
pop %rip
leave指令
相当于执行以下指令:
mov %rbp,%rsp
pop %rbp
指令后缀
b(8位)
w(16位)
l(32位)
q(64位)
函数调用
caller执行call之后的栈帧:
arg n
...
arg 2
arg 1
ret <- rsp
callee开始:
push %rbp
mov %rsp, %rbp
sub $4n, %rsp # var入栈
arg n <- rbp + 4(n+1)
...
arg 2 <- rbp + 12
arg 1 <- rbp + 8
ret <- rbp + 4
rbp <- rbp
var 1 <- rbp - 4
var 2 <- rbp - 8
...
var n <- rbp - 4n/rsp
通过x(%rbp)可以访问函数参数(x为正数)和局部变量(x为负数)
执行函数主体,返回值放入rax
callee结束:
mov %rbp, %rsp # var出栈
pop %rbp # rbp出栈到rbp
ret # ret出栈到rip
传参顺序
前6个参数使用rdi、rsi、rdx、rcx、r8、r9,第7个及以后参数使用栈
c代码
int g(int a, int b)
{
return a + b;
}
int f(int a, int b)
{
return g(a, b);
}
int main()
{
return f(1, 2);
}
编译&反汇编
gcc test.c -o test -g
objdump -dS test
c&汇编代码
00000000004004ed <g>:
int g(int a, int b)
{
4004ed: 55 push %rbp
4004ee: 48 89 e5 mov %rsp,%rbp
4004f1: 89 7d fc mov %edi,-0x4(%rbp)
4004f4: 89 75 f8 mov %esi,-0x8(%rbp)
return a + b;
4004f7: 8b 45 f8 mov -0x8(%rbp),%eax
4004fa: 8b 55 fc mov -0x4(%rbp),%edx
4004fd: 01 d0 add %edx,%eax
}
4004ff: 5d pop %rbp
400500: c3 retq
0000000000400501 <f>:
int f(int a, int b)
{
400501: 55 push %rbp
400502: 48 89 e5 mov %rsp,%rbp
400505: 48 83 ec 08 sub $0x8,%rsp
400509: 89 7d fc mov %edi,-0x4(%rbp)
40050c: 89 75 f8 mov %esi,-0x8(%rbp)
return g(a, b);
40050f: 8b 55 f8 mov -0x8(%rbp),%edx
400512: 8b 45 fc mov -0x4(%rbp),%eax
400515: 89 d6 mov %edx,%esi
400517: 89 c7 mov %eax,%edi
400519: e8 cf ff ff ff callq 4004ed <g>
}
40051e: c9 leaveq
40051f: c3 retq
0000000000400520 <main>:
int main()
{
400520: 55 push %rbp
400521: 48 89 e5 mov %rsp,%rbp
return f(1, 2);
400524: be 02 00 00 00 mov $0x2,%esi
400529: bf 01 00 00 00 mov $0x1,%edi
40052e: e8 ce ff ff ff callq 400501 <f>
}
400533: 5d pop %rbp
400534: c3 retq
400535: 66 2e 0f 1f 84 00 00 nopw %cs:0x0(%rax,%rax,1)
40053c: 00 00 00
40053f: 90 nop
栈帧变化过程
不同颜色代表不同函数的栈帧,从上到下依次是__libc_start_main、main、f、g的栈帧
下一级函数的rbp指向上一级函数的rbp