新闻中心

EEPW首页>嵌入式系统>设计应用> C语言函数调用分析

C语言函数调用分析

作者: 时间:2016-12-01 来源:网络 收藏
我的测试环境:Fedora14
Gcc版本:gcc-4.5.1
内核版本:2.6.38.1
C语言是一个强大的语言,特别是对于嵌入式开发过程中有时需要反汇编分析代码中存在的问题,函数是C语言中的难点,关于函数的调用也是很多人不能理解的,很多知道的也是一知半解。对C语言的调用有了一个比较清晰的认识就能够更清晰的分析代码中存在的问题。我也是看了很多的资料,然后自己写了一一段小代码作为分析的测试代码。首先记住在X86体系里很多的寄存器都有特殊的用途,其中ESP表示当前函数堆栈的栈顶指针,而EBP则表示当前函数堆栈的基地址。EBP是栈基址的指针,永远指向栈底(高地址),ESP是栈指针,永远指向栈顶(低地址)。
我的代码如下:
  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. }
对上面的代码进行编译和反汇编:
[gong@Gong-Computer deeplearn]$ gcc -g testcall.c -o testcall
[gong@Gong-Computer deeplearn]$ objdump -S -d testcall > testcall_s
然后对反汇编的代码进行分析:
  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函数开始的,但是从反汇编代码中可以发现并不是只有自己设计的代码,还存在很多关于初始化等操作。这主要是因为C语言的运行需要一些基本的环境和C-RunTime的一些基本函数。因此main 函数只是我们C语言的入口,但并不是一个程序的开始。因此main函数也需要堆栈的控制,也需要压栈出栈等操作。
需要注意的是:
上一页 1 2 3 下一页

关键词:C语言函数调

评论


技术专区

关闭