新聞中心

        EEPW首頁 > 嵌入式系統(tǒng) > 設(shè)計(jì)應(yīng)用 > C語言函數(shù)調(diào)用分析

        C語言函數(shù)調(diào)用分析

        作者: 時(shí)間:2016-12-01 來源:網(wǎng)絡(luò) 收藏
        指令call用來調(diào)用一個(gè)函數(shù)或過程,這時(shí)下一條指令地址被壓入堆棧中,以備返回時(shí)能恢復(fù)執(zhí)行下條指令。sp=sp-1。通過下面的匯編代碼就可知道函數(shù)的返回地址。
        80483e2: e8 ad ff ff ff call 8048394
        }
        80483e7: c9 leave
        可以知道指令call后的返回地址就是80483e7。而8048394則說明被調(diào)用函數(shù)的起始地址,這些數(shù)字可能在不同的系統(tǒng)中存在差別。
        RET指令用來從一個(gè)函數(shù)或過程返回,之前CALL保存的下條指令地址會(huì)從棧內(nèi)彈出到EIP寄存器中,程序轉(zhuǎn)到CALL之前下條指令處執(zhí)行。
        下面簡單的介紹幾個(gè)代碼:
        80483e9: 55 push %ebp
        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指向同一個(gè)地址,作為被調(diào)用函數(shù)的棧幀基地址。sub $0x18,%esp則是修改ESP的值,與EBP構(gòu)成當(dāng)前被調(diào)用函數(shù)的棧幀空間。
        從圖中可以每個(gè)函數(shù)的棧空間都是相互獨(dú)立的,但是每一個(gè)棧空間的基本結(jié)構(gòu)都是相同的。都是該函數(shù)的EBP指針,然后是局部變量空間,然后是往下一個(gè)函數(shù)的傳遞參數(shù)空間,返回的EBP地址。這樣就能實(shí)現(xiàn)不同函數(shù)的調(diào)用,然后傳遞參數(shù)是采用基于EBP指針的相對(duì)位置實(shí)現(xiàn)的,并沒有絕對(duì)地址。
        由此可以知道棧空間的分布是根據(jù)調(diào)用情況分析的,當(dāng)調(diào)用過多時(shí)就會(huì)導(dǎo)致溢出錯(cuò)誤,因此并不是一味的迭代和遞歸。
        關(guān)于函數(shù)調(diào)用的返回都是采用EAX寄存器實(shí)現(xiàn)的,但是當(dāng)返回的是結(jié)構(gòu)體以及聯(lián)合體時(shí)返回就不能采用EAX實(shí)現(xiàn)了,基本的實(shí)現(xiàn)方法也是基于堆棧的。
        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. }
        編譯以及反匯編以后得到如下的結(jié)果:
        [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. ...
        從上面的結(jié)果可以知道可以知道,返回的過程并不是一次通過EAX返回的,而是通過堆棧一個(gè)一個(gè)的傳遞出來,實(shí)現(xiàn)結(jié)果的返回。因此這也是我們需要注意的地方。
        同樣對(duì)于結(jié)構(gòu)體的傳遞方式也是采用堆棧的方式進(jìn)行傳遞,基本的參看下面的分析。參數(shù)也是依據(jù)堆棧中的位置進(jìn)行控制的。

        關(guān)鍵詞: C語言函數(shù)調(diào)

        評(píng)論


        技術(shù)專區(qū)

        關(guān)閉
        主站蜘蛛池模板: 河西区| 抚顺县| 绍兴县| 嘉祥县| 柞水县| 固原市| 木里| 于田县| 东安县| 韶关市| 苍山县| 唐山市| 叶城县| 湘潭市| 时尚| 揭东县| 离岛区| 岱山县| 泾川县| 阳泉市| 湛江市| 巴中市| 宜兰县| 观塘区| 彰武县| 阳泉市| 杭州市| 伊金霍洛旗| 沙河市| 凌源市| 齐齐哈尔市| 浦东新区| 神农架林区| 梓潼县| 崇州市| 华容县| 盱眙县| 伊川县| 黑山县| 恩平市| 台东县|