1. 最簡(jiǎn)單的代碼: //// test1.c int main(){ return 1; } 編譯、反匯編: gcc test1.c gdb ./a.out (gdb)
disassemble main 0x08048344
<main+0>: lea 0x4(%esp),%ecx ;取出esp寄存器里的值,加上4,將得到值傳遞給ecx; 0x08048348
<main+4>: and $0xfffffff0,%esp ;使棧地址16字節(jié)對(duì)齊 0x0804834b
<main+7>: pushl -0x4(%ecx)
;取出寄存器ecx的值,減去4,即esp的值,將得到的值作為地址,在內(nèi)存找到該地址對(duì)應(yīng)的值,將其壓入棧中。 0x0804834e
<main+10>: push %ebp 0x 0x08048351
<main+13>: push %ecx 0x08048352
<main+14>: mov $0x1,%eax 0x08048357
<main+19>: pop %ecx 0x08048358
<main+20>: pop %ebp 0x08048359
<main+21>: lea -0x4(%ecx),%esp ;取出ecx 寄存器里的值,減去4,將得到值傳遞給esp;還原esp的值 0x 常用指令解釋: CALL指令: 用來(lái)調(diào)用一個(gè)函數(shù)或過(guò)程,此時(shí),下一條指令地址會(huì)被壓入堆棧,以備返回時(shí)能恢復(fù)執(zhí)行下條指令。 用來(lái)從一個(gè)函數(shù)或過(guò)程返回,之前CALL保存的下條指令地址會(huì)從棧內(nèi)彈出到EIP寄存器中,程序轉(zhuǎn)到CALL之前下條指令處執(zhí)行 ENTER指令: 建立當(dāng)前函數(shù)的??蚣?,即相當(dāng)于以下兩條指令: 釋放當(dāng)前函數(shù)或者過(guò)程的??蚣?,即相當(dāng)于以下兩條指令: 2. 函數(shù)間的調(diào)用代碼: 假如函數(shù)A調(diào)用函數(shù)B,函數(shù)B調(diào)用函數(shù)C: ///// test2.c void c(){} void b(){c();} void a(){b();} int main(){ a(); return 1; } 編譯、反匯編: gcc test1.c gdb ./a.out (gdb) disassemble main Dump of assembler code for function main: 0x0804835d <main+0>: lea 0x4(%esp),%ecx 0x08048361 <main+4>: and $0xfffffff0,%esp 0x08048364 <main+7>: pushl -0x4(%ecx) 0x08048367 <main+10>: push %ebp 0x08048368 <main+11>: mov %esp,%ebp 0x 0x0804836b <main+14>: call 0x8048353 <a> 0x08048370 <main+19>: mov $0x1,%eax 0x08048375 <main+24>: pop %ecx 0x08048376 <main+25>: pop %ebp 0x08048377 <main+26>: lea -0x4(%ecx),%esp 0x End of assembler dump. (gdb) disassemble a Dump of assembler code for function a: 0x08048353 <a+0>: push %ebp 0x08048354 <a+1>: mov %esp,%ebp 0x08048356 <a+3>: call 0x8048349 <b> 0x0804835b <a+8>: pop %ebp 0x End of assembler dump. (gdb) disassemble b Dump of assembler code for function b: 0x08048349 <b+0>: push %ebp 0x 0x 0x08048351 <b+8>: pop %ebp 0x08048352 <b+9>: ret End of assembler dump. (gdb) disassemble c Dump of assembler code for function c: 0x08048344 <c+0>: push %ebp 0x08048345 <c+1>: mov %esp,%ebp 0x08048347 <c+3>: pop %ebp 0x08048348 <c+4>: ret End of assembler dump. 函數(shù)調(diào)用棧的狀態(tài): +-------------------------+----> 高地址 | EIP (A函數(shù)的返回地址) | | +-------------------------+----> 低地址 函數(shù)被調(diào)用時(shí): 3含局部變量時(shí): int main(){ int a = 3; int b = 5; return 1; } (gdb) disassemble
main Dump of assembler
code for function main: 0x08048344
<main+0>: lea 0x4(%esp),%ecx 0x08048348
<main+4>: and $0xfffffff0,%esp 0x0804834b
<main+7>: pushl -0x4(%ecx) 0x0804834e
<main+10>: push %ebp 0x 0x08048351
<main+13>: push %ecx 0x08048352
<main+14>: sub $0x10,%esp 0x08048355
<main+17>: movl $0x3,-0x8(%ebp) ; a = 3 0x 0x08048363
<main+31>: mov $0x1,%eax ;return 1; 0x08048368
<main+36>: add $0x10,%esp 0x0804836b
<main+39>: pop %ecx 0x 0x0804836d
<main+41>: lea -0x4(%ecx),%esp 0x08048370
<main+44>: ret End of assembler dump. 通過(guò)反匯編代碼對(duì)程序運(yùn)行時(shí)的寄存器和棧的觀察和分析,可以得出局部變量在棧中的訪問(wèn)和分配及釋放方式:
2.局部變量的釋放,可以通過(guò)esp加上已分配的字節(jié) 4. 函數(shù)調(diào)用時(shí)有參數(shù) int
func(int m, int n) { return m+n; } int main(){ int a = 3; int b = 5; int c = 0; c = func(a, b); return c; } (gdb) disassemble
main Dump of assembler
code for function main: 0x 0x08048353
<main+4>: and $0xfffffff0,%esp 0x08048356
<main+7>: pushl -0x4(%ecx) 0x08048359
<main+10>: push %ebp 0x 0x 0x0804835d
<main+14>: sub $0x18,%esp 0x08048360
<main+17>: movl $0x3,-0x8(%ebp) ;a = 3 0x08048367
<main+24>: movl $0x5,-0xc(%ebp) ;b = 5 0x0804836e
<main+31>: movl $0x0,-0x10(%ebp) ;c = 0; 0x08048375
<main+38>: mov -0xc(%ebp),%eax 0x08048378
<main+41>: mov %eax,0x4(%esp) ; n = b 0x 0x 0x08048382
<main+51>: call 0x8048344 <func> ;func(a,b); 0x08048387
<main+56>: mov %eax,-0x10(%ebp) ; c = func(a, b); 0x 0x0804838d
<main+62>: add $0x18,%esp 0x08048390
<main+65>: pop %ecx 0x08048391
<main+66>: pop %ebp 0x08048392
<main+67>: lea -0x4(%ecx),%esp 0x08048395
<main+70>: ret End of assembler
dump. (gdb) disassemble
func Dump of assembler
code for function func: 0x08048344
<func+0>: push %ebp 0x08048345
<func+1>: mov %esp,%ebp 0x08048347 <func+3>: mov 0xc(%ebp),%eax ; n 0x 0x0804834d
<func+9>: pop %ebp 0x0804834e
<func+10>: ret End of assembler
dump. 參數(shù)的訪問(wèn),可以通過(guò)ebp加上減去偏移量: mov 0xc(%ebp),%eax |
|