x86-64寄存器:
x86-64栈结构
-
函数的调用与栈有着密切的关系,程序的执行通常是一个函数嵌套着下一个函数,无论嵌套有多深,程序总是能正确的返回到原点,这个就要依赖于栈的结构、rsp栈指针寄存器以及rbp栈基地址寄存器
-
假设函数调用关系如下:main()->func1()->func2()
例子:stack.c
unsigned long func2(unsigned long f2)
{
unsigned long i2 = 2;
f2 += i2;
return f2;
}
unsigned long func1(unsigned long f1)
{
unsigned long i1 = 1;
f1+=i1;
f1 = func2(f1);
return f1;
}
int main()
{
unsigned long m = func1(0);
return m;
}
编译:
gcc stack.c
反汇编
objdump -S a.out > stack.S
stack.S:
00000000004004d6 <func2>:
4004d6: 55 push %rbp
4004d7: 48 89 e5 mov %rsp,%rbp
4004da: 48 89 7d e8 mov %rdi,-0x18(%rbp)
4004de: 48 c7 45 f8 02 00 00 movq $0x2,-0x8(%rbp)
4004e5: 00
4004e6: 48 8b 45 f8 mov -0x8(%rbp),%rax
4004ea: 48 01 45 e8 add %rax,-0x18(%rbp)
4004ee: 48 8b 45 e8 mov -0x18(%rbp),%rax
4004f2: 5d pop %rbp
4004f3: c3 retq
00000000004004f4 <func1>:
4004f4: 55 push %rbp
4004f5: 48 89 e5 mov %rsp,%rbp
4004f8: 48 83 ec 18 sub $0x18,%rsp
4004fc: 48 89 7d e8 mov %rdi,-0x18(%rbp)
400500: 48 c7 45 f8 01 00 00 movq $0x1,-0x8(%rbp)
400507: 00
400508: 48 8b 45 f8 mov -0x8(%rbp),%rax
40050c: 48 01 45 e8 add %rax,-0x18(%rbp)
400510: 48 8b 45 e8 mov -0x18(%rbp),%rax
400514: 48 89 c7 mov %rax,%rdi
400517: e8 ba ff ff ff callq 4004d6 <func2>
40051c: 48 89 45 e8 mov %rax,-0x18(%rbp)
400520: 48 8b 45 e8 mov -0x18(%rbp),%rax
400524: c9 leaveq
400525: c3 retq
0000000000400526 <main>:
400526: 55 push %rbp
400527: 48 89 e5 mov %rsp,%rbp
40052a: 48 83 ec 10 sub $0x10,%rsp
40052e: bf 00 00 00 00 mov $0x0,%edi
400533: e8 bc ff ff ff callq 4004f4 <func1>
400538: 48 89 45 f8 mov %rax,-0x8(%rbp)
40053c: 48 8b 45 f8 mov -0x8(%rbp),%rax
400540: c9 leaveq
400541: c3 retq
400542: 66 2e 0f 1f 84 00 00 nopw %cs:0x0(%rax,%rax,1)
400549: 00 00 00
40054c: 0f 1f 40 00 nopl 0x0(%rax)
假如栈开始的地址为0x1000
栈结构: