C語言函數(shù)調(diào)用分析
指令call用來調(diào)用一個函數(shù)或過程,這時下一條指令地址被壓入堆棧中,以備返回時能恢復(fù)執(zhí)行下條指令。sp=sp-1。通過下面的匯編代碼就可知道函數(shù)的返回地址。
80483e2: e8 ad ff ff ff call 8048394
}
80483e7: c9 leave
}
80483e7: c9 leave
可以知道指令call后的返回地址就是80483e7。而8048394則說明被調(diào)用函數(shù)的起始地址,這些數(shù)字可能在不同的系統(tǒng)中存在差別。
RET指令用來從一個函數(shù)或過程返回,之前CALL保存的下條指令地址會從棧內(nèi)彈出到EIP寄存器中,程序轉(zhuǎn)到CALL之前下條指令處執(zhí)行。
下面簡單的介紹幾個代碼:
80483e9: 55 push %ebp
80483ea: 89 e5 mov %esp,%ebp
80483ec: 83 ec 18 sub $0x18,%esp
80483ea: 89 e5 mov %esp,%ebp
80483ec: 83 ec 18 sub $0x18,%esp
首先push %ebp,是將調(diào)用函數(shù)的棧幀基地址壓入棧中,也就是保存調(diào)用函數(shù)的棧幀EBP。將其指向的地址壓入堆棧中。mov %esp,%ebp則是將ESP和EBP指向同一個地址,作為被調(diào)用函數(shù)的棧幀基地址。sub $0x18,%esp則是修改ESP的值,與EBP構(gòu)成當(dāng)前被調(diào)用函數(shù)的棧幀空間。
從圖中可以每個函數(shù)的??臻g都是相互獨立的,但是每一個??臻g的基本結(jié)構(gòu)都是相同的。都是該函數(shù)的EBP指針,然后是局部變量空間,然后是往下一個函數(shù)的傳遞參數(shù)空間,返回的EBP地址。這樣就能實現(xiàn)不同函數(shù)的調(diào)用,然后傳遞參數(shù)是采用基于EBP指針的相對位置實現(xiàn)的,并沒有絕對地址。
由此可以知道??臻g的分布是根據(jù)調(diào)用情況分析的,當(dāng)調(diào)用過多時就會導(dǎo)致溢出錯誤,因此并不是一味的迭代和遞歸。
關(guān)于函數(shù)調(diào)用的返回都是采用EAX寄存器實現(xiàn)的,但是當(dāng)返回的是結(jié)構(gòu)體以及聯(lián)合體時返回就不能采用EAX實現(xiàn)了,基本的實現(xiàn)方法也是基于堆棧的。
- #include
- typedef struct{
- doubled;
- float f;
- inti;
- char c;
- }return_value;
- return_value my_test_of_return()
- {
- return_value rv;
- rv.d=12.56;
- rv.f=3.1;
- rv.i=10;
- rv.c=a;
- return rv;
- }
- intmain()
- {
- return_value local=my_test_of_return();
- return 0;
- }
編譯以及反匯編以后得到如下的結(jié)果:
[gong@Gong-Computer deeplearn]$ gcc -g structpass.c -o structpass
[gong@Gong-Computer deeplearn]$ objdump -S -d structpass > structpass_s
[gong@Gong-Computer deeplearn]$ objdump -S -d structpass > structpass_s
- ...
- 08048394
: - char c;
- }return_value;
- return_value my_test_of_return()
- {
- 8048394: 55 push %ebp
- 8048395: 89 e5 mov %esp,%ebp
- 8048397: 83 ec 20 sub $0x20,%esp
- 804839a: 8b 45 08 mov 0x8(%ebp),%eax
- return_value rv;
- rv.d = 12.56;
- 804839d: dd 05 d8 84 04 08 fldl 0x80484d8
- 80483a3: dd 5d e8 fstpl -0x18(%ebp)
- rv.f = 3.1;
- 80483a6: ba 66 66 46 40 mov $0x40466666,%edx
- 80483ab: 89 55 f0 mov %edx,-0x10(%ebp)
- rv.i = 10;
- 80483ae: c7 45 f4 0a 00 00 00 movl $0xa,-0xc(%ebp)
- rv.c = a;
- 80483b5: c6 45 f8 61 movb $0x61,-0x8(%ebp)
- return rv;
- 80483b9: 8b 55 e8 mov -0x18(%ebp),%edx
- 80483bc: 89 10 mov %edx,(%eax)
- 80483be: 8b 55 ec mov -0x14(%ebp),%edx
- 80483c1: 89 50 04 mov %edx,0x4(%eax)
- 80483c4: 8b 55 f0 mov -0x10(%ebp),%edx
- 80483c7: 89 50 08 mov %edx,0x8(%eax)
- 80483ca: 8b 55 f4 mov -0xc(%ebp),%edx
- 80483cd: 89 50 0c mov %edx,0xc(%eax)
- 80483d0: 8b 55 f8 mov -0x8(%ebp),%edx
- 80483d3: 89 50 10 mov %edx,0x10(%eax)
- }
- 80483d6: c9 leave
- 80483d7: c2 04 00 ret $0x4
- 080483da
: - int main()
- {
- 80483da: 8d 4c 24 04 lea 0x4(%esp),%ecx
- 80483de: 83 e4 f8 and $0xfffffff8,%esp
- 80483e1: ff 71 fc pushl -0x4(%ecx)
- 80483e4: 55 push %ebp
- 80483e5: 89 e5 mov %esp,%ebp
- 80483e7: 51 push %ecx
- 80483e8: 83 ec 2c sub $0x2c,%esp
- return_value local = my_test_of_return();
- 80483eb: 8d 45 e0 lea -0x20(%ebp),%eax
- 80483ee: 89 04 24 mov %eax,(%esp)
- 80483f1: e8 9e ff ff ffcall8048394
- 80483f6: 83 ec 04 sub $0x4,%esp
- return 0;
- 80483f9: b8 00 00 00 00 mov $0x0,%eax
- }
- 80483fe: 8b 4d fc mov -0x4(%ebp),%ecx
- 8048401: c9 leave
- 8048402: 8d 61 fc lea -0x4(%ecx),%esp
- ...
從上面的結(jié)果可以知道可以知道,返回的過程并不是一次通過EAX返回的,而是通過堆棧一個一個的傳遞出來,實現(xiàn)結(jié)果的返回。因此這也是我們需要注意的地方。
看屁屁www成人影院,亚洲人妻成人图片,亚洲精品成人午夜在线,日韩在线 欧美成人
(function(){
var bp = document.createElement('script');
var curProtocol = window.location.protocol.split(':')[0];
if (curProtocol === 'https') {
bp.src = 'https://zz.bdstatic.com/linksubmit/push.js';
}
else {
bp.src = 'http://push.zhanzhang.baidu.com/push.js';
}
var s = document.getElementsByTagName("script")[0];
s.parentNode.insertBefore(bp, s);
})();
關(guān)鍵詞:
C語言函數(shù)調(diào)
相關(guān)推薦
技術(shù)專區(qū)
- FPGA
- DSP
- MCU
- 示波器
- 步進(jìn)電機(jī)
- Zigbee
- LabVIEW
- Arduino
- RFID
- NFC
- STM32
- Protel
- GPS
- MSP430
- Multisim
- 濾波器
- CAN總線
- 開關(guān)電源
- 單片機(jī)
- PCB
- USB
- ARM
- CPLD
- 連接器
- MEMS
- CMOS
- MIPS
- EMC
- EDA
- ROM
- 陀螺儀
- VHDL
- 比較器
- Verilog
- 穩(wěn)壓電源
- RAM
- AVR
- 傳感器
- 可控硅
- IGBT
- 嵌入式開發(fā)
- 逆變器
- Quartus
- RS-232
- Cyclone
- 電位器
- 電機(jī)控制
- 藍(lán)牙
- PLC
- PWM
- 汽車電子
- 轉(zhuǎn)換器
- 電源管理
- 信號放大器
評論