函数调用栈
EIP, EBP, ESP三个指针寄存器与函数调用的关系
函数调用离不开这三个寄存器,函数调用时三者的作用:
EIP中保存CPU下次要执行的指令地址即调用完函数后要执行的指令地址;
EBP中保存的是当前函数栈基地址,一直不变,即栈底;
ESP 中保存的是当前函数调用栈顶
函数参数与EBP关系
由上图我们可以看出,函数的参数与EBP的关系,第一个参数与EBP之间隔着上一级函数的EIP,EBP。由于EIP, EBP都是指针所以占4个字节, 第一个参数与EBP相隔8个字节。函数参数是由右向左依次压栈的,所以得如下结论:
第一个参数地址 = EBP的值 + 8
第二个参数地址 = EBP的值 + 8 + sizeof(参数1)
第N个参数地址 = EBP的值+8 + sizeof(参数1) + sizeof(参数2) …sizeof(参数N-1);
依此类推可以根据EBP的值和各参数的类型我们可以找到所有参数
注:如果是C++的类型成员函数则第一个参数是this指针
test.c
1 |
|
test.s
1 | .file "test.c" |
- call *8(%eax)
调用 %eax+8 ,的函数指针指向的函数。 - incw 0xffffffc8(%ebp,%ecx,2)
(ebp + 2ecx) - (0x100-0xc8),这个值进行++操作
这是基址变址寻址方式,disp(base, index, scale),计算方法:base+indexscale+disp 。 - movb 0x15 0x16(%esp,1)
移动字节0x15,到%esp*1+0x16,这个地址上。
属变址寻址方式
linux中一个进程的内存布局如下图所示:
1 |
|
int a=16777220,十六进制是0x01 00 00 04则04属于低字节,01属于高字节
大端 网络 | 小端 主机 | |
---|---|---|
0x0004 | 04 | 01 |
0x0003 | 00 | 00 |
0x0002 | 00 | 00 |
0x0001 | 01 | 04 |
(1)一个整数类型内部
低地址存储低位,高地址存储高位。比如int a=1,则存储情况为0000(高地址) 0000 0000 0001(低地址)
(2)若干个局部变量(在栈中存储的)
先定义的高地址,后定义的低地址
(3)类、结构体或数组的元素
先定义的低地址,后定义的高地址