新聞中心

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

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

作者: 時間:2016-12-01 來源:網(wǎng)絡(luò) 收藏
我的測試環(huán)境:Fedora14
Gcc版本:gcc-4.5.1
內(nèi)核版本:2.6.38.1
C語言是一個強大的語言,特別是對于嵌入式開發(fā)過程中有時需要反匯編分析代碼中存在的問題,函數(shù)是C語言中的難點,關(guān)于函數(shù)的調(diào)用也是很多人不能理解的,很多知道的也是一知半解。對C語言的調(diào)用有了一個比較清晰的認(rèn)識就能夠更清晰的分析代碼中存在的問題。我也是看了很多的資料,然后自己寫了一一段小代碼作為分析的測試代碼。首先記住在X86體系里很多的寄存器都有特殊的用途,其中ESP表示當(dāng)前函數(shù)堆棧的棧頂指針,而EBP則表示當(dāng)前函數(shù)堆棧的基地址。EBP是?;返闹羔?,永遠(yuǎn)指向棧底(高地址),ESP是棧指針,永遠(yuǎn)指向棧頂(低地址)。
我的代碼如下:
  1. #include

  2. intpluss_a_and_b(inta,intb)
  3. {
  4. intc=-2;
  5. return(a+b-c);
  6. }
  7. intcall_plus(int*a,int*b)
  8. {
  9. intc=*a;
  10. intd=*b;

  11. *a=d;
  12. *b=c;
  13. return pluss_a_and_b(c,d);
  14. }
  15. intmain()
  16. {
  17. intc=10;
  18. intd=20;
  19. intg=call_plus(&c,&d);
  20. return 0;
  21. }
對上面的代碼進(jìn)行編譯和反匯編:
[gong@Gong-Computer deeplearn]$ gcc -g testcall.c -o testcall
[gong@Gong-Computer deeplearn]$ objdump -S -d testcall > testcall_s
然后對反匯編的代碼進(jìn)行分析:
  1. ...
  2. 8048393: c3 ret
  3. 08048394 :
  4. #include
  5. int pluss_a_and_b(int a,int b)
  6. {
  7. 8048394: 55 push %ebp
  8. 8048395: 89 e5 mov %esp,%ebp
  9. 8048397: 83 ec 10 sub $0x10,%esp
  10. int c = -2;
  11. 804839a: c7 45 fc fe ff ff ff movl $0xfffffffe,-0x4(%ebp)
  12. return (a + b - c);
  13. 80483a1: 8b 45 0c mov 0xc(%ebp),%eax
  14. 80483a4: 8b 55 08 mov 0x8(%ebp),%edx
  15. 80483a7: 8d 04 02 lea (%edx,%eax,1),%eax
  16. 80483aa: 2b 45 fc sub -0x4(%ebp),%eax
  17. }
  18. 80483ad: c9 leave
  19. 80483ae: c3 ret
  20. 080483af :
  21. intcall_plus(int *a,int *b)
  22. {
  23. 80483af: 55 push %ebp
  24. 80483b0: 89 e5 mov %esp,%ebp
  25. 80483b2: 83 ec 18 sub $0x18,%esp
  26. int c = *a;
  27. 80483b5: 8b 45 08 mov 0x8(%ebp),%eax
  28. 80483b8: 8b 00 mov (%eax),%eax
  29. 80483ba: 89 45 fc mov %eax,-0x4(%ebp)
  30. int d = *b;
  31. 80483bd: 8b 45 0c mov 0xc(%ebp),%eax
  32. 80483c0: 8b 00 mov (%eax),%eax
  33. 80483c2: 89 45 f8 mov %eax,-0x8(%ebp)
  34. *a = d;
  35. 80483c5: 8b 45 08 mov 0x8(%ebp),%eax
  36. 80483c8: 8b 55 f8 mov -0x8(%ebp),%edx
  37. 80483cb: 89 10 mov %edx,(%eax)
  38. *b = c;
  39. 80483cd: 8b 45 0c mov 0xc(%ebp),%eax
  40. 80483d0: 8b 55 fc mov -0x4(%ebp),%edx
  41. 80483d3: 89 10 mov %edx,(%eax)
  42. return pluss_a_and_b(c,d);
  43. 80483d5: 8b 45 f8 mov -0x8(%ebp),%eax
  44. 80483d8: 89 44 24 04 mov %eax,0x4(%esp)
  45. 80483dc: 8b 45 fc mov -0x4(%ebp),%eax
  46. 80483df: 89 04 24 mov %eax,(%esp)
  47. 80483e2: e8 ad ff ff ff call 8048394
  48. }
  49. 80483e7: c9 leave
  50. 80483e8: c3 ret
  51. 080483e9
    :
  52. int main()
  53. {
  54. 80483e9: 55 push %ebp
  55. 80483ea: 89 e5 mov %esp,%ebp
  56. 80483ec: 83 ec 18 sub $0x18,%esp
  57. int c = 10;
  58. 80483ef: c7 45 f8 0a 00 00 00 movl $0xa,-0x8(%ebp)
  59. int d = 20;
  60. 80483f6: c7 45 f4 14 00 00 00 movl $0x14,-0xc(%ebp)
  61. int g =call_plus(&c,&d);
  62. 80483fd: 8d 45 f4 lea -0xc(%ebp),%eax
  63. 8048400: 89 44 24 04 mov %eax,0x4(%esp)
  64. 8048404: 8d 45 f8 lea -0x8(%ebp),%eax
  65. 8048407: 89 04 24 mov %eax,(%esp)
  66. 804840a: e8 a0 ff ff ff call 80483af
  67. 804840f: 89 45 fc mov %eax,-0x4(%ebp)
  68. return 0;
  69. 8048412: b8 00 00 00 00 mov $0x0,%eax
  70. }
  71. 8048417: c9 leave
  72. 8048418: c3 ret
  73. 8048419: 90 nop
  74. 804841a: 90nop
  75. ...
首先,C語言的入口都是從main函數(shù)開始的,但是從反匯編代碼中可以發(fā)現(xiàn)并不是只有自己設(shè)計的代碼,還存在很多關(guān)于初始化等操作。這主要是因為C語言的運行需要一些基本的環(huán)境和C-RunTime的一些基本函數(shù)。因此main 函數(shù)只是我們C語言的入口,但并不是一個程序的開始。因此main函數(shù)也需要堆棧的控制,也需要壓棧出棧等操作。
需要注意的是:
上一頁 1 2 3 下一頁

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

評論


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

關(guān)閉