C语言函数调用参数传递栈详解.docx
《C语言函数调用参数传递栈详解.docx》由会员分享,可在线阅读,更多相关《C语言函数调用参数传递栈详解.docx(14页珍藏版)》请在冰点文库上搜索。
C语言函数调用参数传递栈详解
C语言调用函数过程详解
Sunny.man
1.使用环境:
gcc版本4.1.220071124(RedHat4.1.2-42)
2.示例源代码
intfoo(inta,intb)
{
inta1=0x123;
returna1+a+b;
}
intmain()
{
foo(2,3);
return0;
}
3.运行程序
命令:
gdba.out
Start
Disassemble
4.汇编函数清单
4.1main函数的汇编
0x0804836c:
lea0x4(%esp),%ecx
0x08048370:
and$0xfffffff0,%esp
0x08048373:
pushl0xfffffffc(%ecx)
0x08048376:
push%ebp
0x08048377:
mov%esp,%ebp
0x08048379:
push%ecx
0x0804837a:
sub$0x8,%esp
0x0804837d:
movl$0x3,0x4(%esp)
0x08048385:
movl$0x2,(%esp)
0x0804838c:
call0x8048354
0x08048391:
mov$0x0,%eax
0x08048396:
add$0x8,%esp
0x08048399:
pop%ecx
0x0804839a:
pop%ebp
0x0804839b:
lea0xfffffffc(%ecx),%esp
0x0804839e:
ret
4.2Foo函数的汇编
0x08048354:
push%ebp
0x08048355:
mov%esp,%ebp
0x08048357:
sub$0x10,%esp
0x0804835a:
movl$0x123,0xfffffffc(%ebp)
0x08048361:
mov0x8(%ebp),%eax
0x08048364:
add0xfffffffc(%ebp),%eax
0x08048367:
add0xc(%ebp),%eax
0x0804836a:
leave
0x0804836b:
ret
5.程序执行时分析
(gdb)inforegisters
eax0xbf820894-1081997164
ecx0xbf820810-1081997296
edx0x11
ebx0x56eff45697524
esp0xbf8207ec0xbf8207ec
ebp0xbf8207f80xbf8207f8
esi0x42cca04377760
edi0x00
eip0x804837d0x804837d
eflags0x200292[AFSFIFID]
cs0x73115
ss0x7b123
ds0x7b123
es0x7b123
fs0x00
gs0x3351
注:
此时已经执行到main的第14行下一条指令是movl$0x3,0x4(%esp)此时的esp是0xbf8207ec。
5.1分析esp=0xbf8207ec的来历
(gdb)x/20$esp
0xbf8207ec:
0x0056eff40x004205d00xbf8208100xbf820868
0xbf8207fc:
0x00445dec0x0042cca00x080483b00xbf820868
0xbf82080c:
0x00445dec0x000000010xbf8208940xbf82089c
0xbf82081c:
0x0042d8100x000000000x000000010x00000001
0xbf82082c:
0x000000000x0056eff40x0042cca00x00000000
5.1.1Main+14
0x0804837a:
sub$0x8,%esp
现在的esp=0xbf8207ecebp=0xbf8207f8eip=0x804837d
则原来esp的值就是0xbf8207ec+0x8=0xbf8207f4
5.1.2Main+13
0x08048379:
push%ecx
Esp=0xbf8207f4+0x04=0xbf8207f8
5.1.3Main+11
0x08048377:
mov%esp,%ebp
Ebp=0xbf8207f8和现在的EBP值是一样的。
5.1.4Main+10
0x08048376:
push%ebp
Esp=0xbf8207f8+4=0xBF8207FC
5.1.5Main+7
0x08048373:
pushl0xfffffffc(%ecx)
ESP的值=0xBF8207FC+4=0xBF820800
5.1.6Main+4
0x08048370:
and$0xfffffff0,%esp
从这句可以看出esp的值是0xBF82080X,无法进一步得出了。
不过没有关系,我们可以通过上一句来看出.
5.1.7Main+0
0x0804836c:
lea0x4(%esp),%ecx
这个说明现在的ecx寄存器中,存着原来Esp的值+4,那我们知道ecx里存的是0xbf820810。
这个值是最初的esp+4那最初的esp就是0xbf82080c。
5.2从main+0开始进行推导
1.最早的esp=0xbf82080cebp=0xbf8207f8
2.现在的各地址的值是:
0xbf8207ec:
0x0056eff40x004205d00xbf8208100xbf820868
0xbf8207fc:
0x00445dec0x0042cca00x080483b00xbf820868
0xbf82080c:
0x00445dec0x000000010xbf8208940xbf82089c
0xbf82081c:
0x0042d8100x000000000x000000010x00000001
0xbf82082c:
0x000000000x0056eff40x0042cca00x00000000
3.0x0804836c:
lea0x4(%esp),%ecx
4.0x08048370:
and$0xfffffff0,%esp
esp=0xbf82080c&0xFFFFFFF0=0xbf820800
5.0x08048373:
pushl0xfffffffc(%ecx)
esp=0xbf820800-4=0xbf8207fcecx所指向的地值-4也就是原来esp(0xbf82080c)所指向的值0x00445dec
6.0x08048376:
push%ebp
esp=0xbf8207fc-4=0xbf8207f8原来的ebp内容=0xbf820868
7.0x08048377:
mov%esp,%ebp
Ebp=esp=0xbf8207f8
8.0x08048379:
push%ecx
Esp=0xbf8207f8=4=0xbf8207f4里面的内容:
0xbf820810来缘是原来的esp(0xbf82080c)+4
9.0x0804837a:
sub$0x8,%esp
Esp=0xbf8207f4-8=0xbf8207ec
10.0x0804837d:
movl$0x3,0x4(%esp)
11.0x08048385:
movl$0x2,(%esp)
12.0x0804838c:
call0x8048354
Call把下一个指令的地址压栈,并esp-4同时改写eip
eax0xbf820894-1081997164
ecx0xbf820810-1081997296
edx0x11
ebx0x56eff45697524
esp0xbf8207e80xbf8207e8
ebp0xbf8207f80xbf8207f8
esi0x42cca04377760
edi0x00
eip0x80483540x8048354
eflags0x200292[AFSFIFID]
cs0x73115
ss0x7b123
ds0x7b123
es0x7b123
fs0x00
gs0x3351
esp=0xbf8207ec-4=0xbf8207e8内容:
0x08048391这个值正式一下条指令Main+37的地址值。
0x08048391:
mov$0x0,%eax
(gdb)x/20$esp
0xbf8207e8:
0x080483910x000000020x000000030xbf820810
0xbf8207f8:
0xbf8208680x00445dec0x0042cca00x080483b0
0xbf820808:
0xbf8208680x00445dec0x000000010xbf820894
0xbf820818:
0xbf82089c0x0042d8100x000000000x00000001
0xbf820828:
0x000000010x000000000x0056eff40x0042cca0
13.0x08048354:
push%ebp
Esp=esp-4=0xbf8207e4
(gdb)inforegisters
eax0xbf820894-1081997164
ecx0xbf820810-1081997296
edx0x11
ebx0x56eff45697524
esp0xbf8207e40xbf8207e4
ebp0xbf8207f80xbf8207f8
esi0x42cca04377760
edi0x00
eip0x80483550x8048355
eflags0x200292[AFSFIFID]
cs0x73115
ss0x7b123
ds0x7b123
es0x7b123
fs0x00
gs0x3351
14.0x08048355:
mov%esp,%ebp
Ebp=esp
(gdb)inforegisters
eax0xbf820894-1081997164
ecx0xbf820810-1081997296
edx0x11
ebx0x56eff45697524
esp0xbf8207e40xbf8207e4
ebp0xbf8207e40xbf8207e4
esi0x42cca04377760
edi0x00
eip0x80483570x8048357
eflags0x200292[AFSFIFID]
cs0x73115
ss0x7b123
ds0x7b123
es0x7b123
fs0x00
gs0x3351
(gdb)x/20$esp
0xbf8207e4:
0xbf8207f80x080483910x000000020x00000003
0xbf8207f4:
0xbf8208100xbf8208680x00445dec0x0042cca0
0xbf820804:
0x080483b00xbf8208680x00445dec0x00000001
0xbf820814:
0xbf8208940xbf82089c0x0042d8100x00000000
0xbf820824:
0x000000010x000000010x000000000x0056eff4
15.0x08048357:
sub$0x10,%esp
Esp=esp-0x10=0xbf8207e4-0x10=0xbf8207d4
16.0x0804835a:
movl$0x123,0xfffffffc(%ebp)
0xfffffffc(%ebp)=0xbf8207e4-4=0xbf8207e0
(gdb)inforegisters
eax0xbf820894-1081997164
ecx0xbf820810-1081997296
edx0x11
ebx0x56eff45697524
esp0xbf8207d40xbf8207d4
ebp0xbf8207e40xbf8207e4
esi0x42cca04377760
edi0x00
eip0x804835a0x804835a
eflags0x200286[PFSFIFID]
cs0x73115
ss0x7b123
ds0x7b123
es0x7b123
fs0x00
gs0x3351
(gdb)x/20$esp
0xbf8207d4:
0x0056d2100xbf8208080x080483c90x00000123
0xbf8207e4:
0xbf8207f80x080483910x000000020x00000003
0xbf8207f4:
0xbf8208100xbf8208680x00445dec0x0042cca0
0xbf820804:
0x080483b00xbf8208680x00445dec0x00000001
0xbf820814:
0xbf8208940xbf82089c0x0042d8100x00000000
Esp=0xbf8207d4Ebp-4=0x123Ebp=0xbf8207e4
17.0x08048361:
mov0x8(%ebp),%eax
18.0x08048364:
add0xfffffffc(%ebp),%eax
19.0x08048367:
add0xc(%ebp),%eax
Ebp+8是传来的参数ebp-4是第一个临时变量
20.0x0804836a:
leave
Leave等同于下列两句
Move$ebp,$esp
pop%ebp
把esp=ebp=0xbf8207e4
ebp=0xbf8207f8
esp=esp+4=0xbf8207e8
(gdb)inforegisters
eax0x128296
ecx0xbf820810-1081997296
edx0x11
ebx0x56eff45697524
esp0xbf8207e80xbf8207e8
ebp0xbf8207f80xbf8207f8
esi0x42cca04377760
edi0x00
eip0x804836b0x804836b
eflags0x200206[PFIFID]
cs0x73115
ss0x7b123
ds0x7b123
es0x7b123
fs0x00
gs0x3351
21.0x0804836b:
ret
pop%eip
esp=esp+4=0xbf8207ec
(gdb)inforeg
eax0x128296
ecx0xbf820810-1081997296
edx0x11
ebx0x56eff45697524
esp0xbf8207ec0xbf8207ec
ebp0xbf8207f80xbf8207f8
esi0x42cca04377760
edi0x00
eip0x80483910x8048391
eflags0x200206[PFIFID]
cs0x73115
ss0x7b123
ds0x7b123
es0x7b123
fs0x00
gs0x3351
22.0x08048396:
add$0x8,%esp
esp=esp+8=0xbf8207ec+8=0xbf8207f4
(gdb)inforegisters
eax0x00
ecx0xbf820810-1081997296
edx0x11
ebx0x56eff45697524
esp0xbf8207f40xbf8207f4
ebp0xbf8207f80xbf8207f8
esi0x42cca04377760
edi0x00
eip0x80483990x8048399
eflags0x200292[AFSFIFID]
cs0x73115
ss0x7b123
ds0x7b123
es0x7b123
fs0x00
gs0x3351
(gdb)x/20$esp
0xbf8207f4:
0xbf8208100xbf8208680x00445dec0x0042cca0
0xbf820804:
0x080483b00xbf8208680x00445dec0x00000001
0xbf820814:
0xbf8208940xbf82089c0x0042d8100x00000000
0xbf820824:
0x000000010x000000010x000000000x0056eff4
0xbf820834:
0x0042cca00x000000000xbf8208680x7f1f8fc0
23.0x08048399:
pop%ecx
esp=esp+4=0xbf8207f8
(gdb)inforegisters
eax0x00
ecx0xbf820810-1081997296
edx0x11
ebx0x56eff45697524
esp0xbf8207f80xbf8207f8
ebp0xbf8207f80xbf8207f8
esi0x42cca04377760
edi0x00
eip0x804839a0x804839a
eflags0x200292[AFSFIFID]
cs0x73115
ss0x7b123
ds0x7b123
es0x7b123
fs0x00
gs0x3351
24.0x0804839a:
pop%ebp
esp=esp+4=0xbf8207fc
ebp=0xbf820868
(gdb)inforegisters
eax0x00
ecx0xbf820810-1081997296
edx0x11
ebx0x56eff45697524
esp0xbf8207fc0xbf8207fc
ebp0xbf8208680xbf820868
esi0x42cca04377760
edi0x00
eip0x804839b0x804839b
eflags0x200292[AFSFIFID]
cs0x73115
ss0x7b123
ds0x7b123
es0x7b123
fs0x00
gs0x3351
25.0x0804839b:
lea0xfffffffc(%ecx),%esp
Esp=0xbf820810-4=0xbf82080c恢复到原来的esp
26.0x0804839e:
ret
等同于pop%eip
Esp=esp+4=0xbf820810
(gdb)inforegisters
eax0x00
ecx0xbf820810-1081997296
edx0x11
ebx0x56eff45697524
esp0xbf8208100xbf820810
ebp0xbf8208680xbf820868
esi0x42cca04377760
edi0x00
eip0x445dec0x445dec<__libc_start_main+220>
eflags0x200292[AFSFIFID]
cs0x73115
ss0x7b123
ds0x7b123
es0x7b123
fs0x00
gs0x3351
27.mov%eax,(%esp)
把0做为返回值传给libc_start_main
0x00445de9<__libc_start_main+217>:
call*0x8(%ebp)
0x00445dec<__libc_start_main+220>:
mov%eax,(%esp)