<dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><s id="yhprb"><strike id="yhprb"></strike></s></dfn><small id="yhprb"></small><dfn id="yhprb"></dfn><small id="yhprb"><delect id="yhprb"></delect></small><small id="yhprb"></small><small id="yhprb"></small> <delect id="yhprb"><strike id="yhprb"></strike></delect><dfn id="yhprb"></dfn><dfn id="yhprb"></dfn><s id="yhprb"><noframes id="yhprb"><small id="yhprb"><dfn id="yhprb"></dfn></small><dfn id="yhprb"><delect id="yhprb"></delect></dfn><small id="yhprb"></small><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn> <small id="yhprb"></small><delect id="yhprb"><strike id="yhprb"></strike></delect><dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"><s id="yhprb"><strike id="yhprb"></strike></s></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn>

新聞中心

EEPW首頁(yè) > 嵌入式系統 > 設計應用 > C語(yǔ)言函數調用分析

C語(yǔ)言函數調用分析

作者: 時(shí)間:2016-12-01 來(lái)源:網(wǎng)絡(luò ) 收藏
指令call用來(lái)調用一個(gè)函數或過(guò)程,這時(shí)下一條指令地址被壓入堆棧中,以備返回時(shí)能恢復執行下條指令。sp=sp-1。通過(guò)下面的匯編代碼就可知道函數的返回地址。
80483e2: e8 ad ff ff ff call 8048394
}
80483e7: c9 leave
可以知道指令call后的返回地址就是80483e7。而8048394則說(shuō)明被調用函數的起始地址,這些數字可能在不同的系統中存在差別。
RET指令用來(lái)從一個(gè)函數或過(guò)程返回,之前CALL保存的下條指令地址會(huì )從棧內彈出到EIP寄存器中,程序轉到CALL之前下條指令處執行。
下面簡(jiǎn)單的介紹幾個(gè)代碼:
80483e9: 55 push %ebp
80483ea: 89 e5 mov %esp,%ebp
80483ec: 83 ec 18 sub $0x18,%esp
首先push %ebp,是將調用函數的棧幀基地址壓入棧中,也就是保存調用函數的棧幀EBP。將其指向的地址壓入堆棧中。mov %esp,%ebp則是將ESP和EBP指向同一個(gè)地址,作為被調用函數的棧幀基地址。sub $0x18,%esp則是修改ESP的值,與EBP構成當前被調用函數的棧幀空間。
從圖中可以每個(gè)函數的??臻g都是相互獨立的,但是每一個(gè)??臻g的基本結構都是相同的。都是該函數的EBP指針,然后是局部變量空間,然后是往下一個(gè)函數的傳遞參數空間,返回的EBP地址。這樣就能實(shí)現不同函數的調用,然后傳遞參數是采用基于EBP指針的相對位置實(shí)現的,并沒(méi)有絕對地址。
由此可以知道??臻g的分布是根據調用情況分析的,當調用過(guò)多時(shí)就會(huì )導致溢出錯誤,因此并不是一味的迭代和遞歸。
關(guān)于函數調用的返回都是采用EAX寄存器實(shí)現的,但是當返回的是結構體以及聯(lián)合體時(shí)返回就不能采用EAX實(shí)現了,基本的實(shí)現方法也是基于堆棧的。
  1. #include

  2. typedef struct{
  3. doubled;
  4. float f;
  5. inti;
  6. char c;
  7. }return_value;


  8. return_value my_test_of_return()
  9. {
  10. return_value rv;

  11. rv.d=12.56;
  12. rv.f=3.1;
  13. rv.i=10;
  14. rv.c=a;

  15. return rv;
  16. }

  17. intmain()
  18. {
  19. return_value local=my_test_of_return();

  20. return 0;
  21. }
編譯以及反匯編以后得到如下的結果:
[gong@Gong-Computer deeplearn]$ gcc -g structpass.c -o structpass
[gong@Gong-Computer deeplearn]$ objdump -S -d structpass > structpass_s
  1. ...
  2. 08048394 :
  3. char c;
  4. }return_value;
  5. return_value my_test_of_return()
  6. {
  7. 8048394: 55 push %ebp
  8. 8048395: 89 e5 mov %esp,%ebp
  9. 8048397: 83 ec 20 sub $0x20,%esp
  10. 804839a: 8b 45 08 mov 0x8(%ebp),%eax
  11. return_value rv;
  12. rv.d = 12.56;
  13. 804839d: dd 05 d8 84 04 08 fldl 0x80484d8
  14. 80483a3: dd 5d e8 fstpl -0x18(%ebp)
  15. rv.f = 3.1;
  16. 80483a6: ba 66 66 46 40 mov $0x40466666,%edx
  17. 80483ab: 89 55 f0 mov %edx,-0x10(%ebp)
  18. rv.i = 10;
  19. 80483ae: c7 45 f4 0a 00 00 00 movl $0xa,-0xc(%ebp)
  20. rv.c = a;
  21. 80483b5: c6 45 f8 61 movb $0x61,-0x8(%ebp)
  22. return rv;
  23. 80483b9: 8b 55 e8 mov -0x18(%ebp),%edx
  24. 80483bc: 89 10 mov %edx,(%eax)
  25. 80483be: 8b 55 ec mov -0x14(%ebp),%edx
  26. 80483c1: 89 50 04 mov %edx,0x4(%eax)
  27. 80483c4: 8b 55 f0 mov -0x10(%ebp),%edx
  28. 80483c7: 89 50 08 mov %edx,0x8(%eax)
  29. 80483ca: 8b 55 f4 mov -0xc(%ebp),%edx
  30. 80483cd: 89 50 0c mov %edx,0xc(%eax)
  31. 80483d0: 8b 55 f8 mov -0x8(%ebp),%edx
  32. 80483d3: 89 50 10 mov %edx,0x10(%eax)
  33. }
  34. 80483d6: c9 leave
  35. 80483d7: c2 04 00 ret $0x4
  36. 080483da
    :
  37. int main()
  38. {
  39. 80483da: 8d 4c 24 04 lea 0x4(%esp),%ecx
  40. 80483de: 83 e4 f8 and $0xfffffff8,%esp
  41. 80483e1: ff 71 fc pushl -0x4(%ecx)
  42. 80483e4: 55 push %ebp
  43. 80483e5: 89 e5 mov %esp,%ebp
  44. 80483e7: 51 push %ecx
  45. 80483e8: 83 ec 2c sub $0x2c,%esp
  46. return_value local = my_test_of_return();
  47. 80483eb: 8d 45 e0 lea -0x20(%ebp),%eax
  48. 80483ee: 89 04 24 mov %eax,(%esp)
  49. 80483f1: e8 9e ff ff ffcall8048394
  50. 80483f6: 83 ec 04 sub $0x4,%esp
  51. return 0;
  52. 80483f9: b8 00 00 00 00 mov $0x0,%eax
  53. }
  54. 80483fe: 8b 4d fc mov -0x4(%ebp),%ecx
  55. 8048401: c9 leave
  56. 8048402: 8d 61 fc lea -0x4(%ecx),%esp
  57. ...
從上面的結果可以知道可以知道,返回的過(guò)程并不是一次通過(guò)EAX返回的,而是通過(guò)堆棧一個(gè)一個(gè)的傳遞出來(lái),實(shí)現結果的返回。因此這也是我們需要注意的地方。
同樣對于結構體的傳遞方式也是采用堆棧的方式進(jìn)行傳遞,基本的參看下面的分析。參數也是依據堆棧中的位置進(jìn)行控制的。

關(guān)鍵詞: C語(yǔ)言函數調

評論


技術(shù)專(zhuān)區

關(guān)閉
国产精品自在自线亚洲|国产精品无圣光一区二区|国产日产欧洲无码视频|久久久一本精品99久久K精品66|欧美人与动牲交片免费播放
<dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><s id="yhprb"><strike id="yhprb"></strike></s></dfn><small id="yhprb"></small><dfn id="yhprb"></dfn><small id="yhprb"><delect id="yhprb"></delect></small><small id="yhprb"></small><small id="yhprb"></small> <delect id="yhprb"><strike id="yhprb"></strike></delect><dfn id="yhprb"></dfn><dfn id="yhprb"></dfn><s id="yhprb"><noframes id="yhprb"><small id="yhprb"><dfn id="yhprb"></dfn></small><dfn id="yhprb"><delect id="yhprb"></delect></dfn><small id="yhprb"></small><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn> <small id="yhprb"></small><delect id="yhprb"><strike id="yhprb"></strike></delect><dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"><s id="yhprb"><strike id="yhprb"></strike></s></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn>