呼叫函式時,暫存器到底發生了那些變化?

weixin_34054866發表於2012-05-01

一直存在比較模糊的概念,因此用一個例子強化記憶。

linux x86 gcc3.2.3 AT&T格式的彙編

程式碼如下:

void
fun()
{
int a = 'A';
}

void
main()
{
int b;
fun();

return;
}


開始除錯
[sanool@sanool ex2]$ gdb a.out
GNU gdb Red Hat Linux (6.0post-0.20031117.6rh)
Copyright 2003 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are
welcome to change it and/or distribute copies of it under certain conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB. Type "show warranty" for details.
This GDB was configured as "i386-redhat-linux-gnu"...(no debugging symbols found)...Using host libthread_db library "/lib/tls/libthread_db.so.1".

(gdb) disas main
Dump of assembler code for function main:
0x08048323 <main+0>: push %ebp
0x08048324 <main+1>: mov %esp,%ebp
0x08048326 <main+3>: sub $0x8,%esp
0x08048329 <main+6>: and $0xfffffff0,%esp
0x0804832c <main+9>: mov $0x0,%eax
0x08048331 <main+14>: sub %eax,%esp
0x08048333 <main+16>: call 0x8048314 <fun>
0x08048338 <main+21>: leave
0x08048339 <main+22>: ret
0x0804833a <main+23>: nop
0x0804833b <main+24>: nop
End of assembler dump.
(gdb) disas fun
Dump of assembler code for function fun:
0x08048314 <fun+0>: push %ebp
0x08048315 <fun+1>: mov %esp,%ebp
0x08048317 <fun+3>: sub $0x4,%esp
0x0804831a <fun+6>: movl $0x41,0xfffffffc(%ebp)
0x08048321 <fun+13>: leave
0x08048322 <fun+14>: ret
End of assembler dump.

解釋如下:
**當程式下一步執行 0x08048333 <main+16>: call 0x8048314 <fun> 時
esp = 0xbfffe660 (執行時)
ebp = 0xbfffe668 (執行時)
eip = 0x08048333

**然後執行 call 0x8048314<fun> 也就是
push %eip ( 相當於 sub $4 %esp 再 mov %eip %esp )
movl $0x8048314, %eip

則0xbfffe65c 處為 eip = 0x08048338
且esp = 0xbfffe65c
eip = 0x8048314
ebp = 0xbfffe668

**執行0x08048314 <fun+0>: push %ebp後
esp = 0xbfffe658
ebp = 0xbfffe668
0xbfffe658處的值為 ebp = 0xbfffe668

**繼續0x08048315 <fun+1>: mov %esp,%ebp
將esp的值賦值給ebp
即 ebp = esp = 0xbfffe658

**開始執行 0x08048321 <fun+13>: leave 前
eip = 0x08048321
ebp = 0xbfffe658
esp = 0xbfffe654

**開始執行 0x08048321 <fun+13>: leave 時
即進行
movl %ebp, %esp ( 即 esp = ebp = 0xbfffe658)
pop %ebp ( 也就是 mov %esp,%ebp 再 add $4,%esp )

此時 ebp = 0xbfffe668 回到了原函式的ebp值,

**再執行 0x08048322 <fun+14>: ret
即 pop %eip
( 也就是 mov %esp,%eip 再 add $4,%esp )
此時 eip = 0x08048338
程式繼續執行 main 中的 leave

呼叫fun函式結束

相關文章