新闻中心

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

C语言函数调用分析

作者: 时间:2016-12-01 来源:网络 收藏
代码:
  1. #include

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

  8. return_value my_test_pass(return_value pass)
  9. {
  10. return_value rv;
  11. rv.d=pass.d;
  12. rv.f=pass.f;
  13. rv.i=pass.i;
  14. rv.c=pass.c;

  15. return rv;
  16. }
  17. return_value my_test_of_return()
  18. {
  19. return_value rv;

  20. rv.d=12.56;
  21. rv.f=3.1;
  22. rv.i=10;
  23. rv.c=a;

  24. return rv;
  25. }

  26. intmain()
  27. {
  28. return_value local=my_test_of_return();
  29. return_value local1=my_test_pass(local);

  30. return 0;
  31. }
编译和反汇编过程:
[gong@Gong-Computer deeplearn]$ gcc -g structpass.c -o structpass
[gong@Gong-Computer deeplearn]$ objdump -S -d structpass > structpass_s
  1. ...
  2. int main()
  3. {
  4. 804841d: 8d 4c 24 04 lea 0x4(%esp),%ecx
  5. 8048421: 83 e4 f8 and $0xfffffff8,%esp
  6. 8048424: ff 71 fc pushl -0x4(%ecx)
  7. 8048427: 55 push %ebp
  8. 8048428: 89 e5 mov %esp,%ebp
  9. 804842a: 51 push %ecx
  10. 804842b: 83 ec 4c sub $0x4c,%esp
  11. return_value local = my_test_of_return();
  12. 804842e: 8d 45 e0 lea -0x20(%ebp),%eax
  13. 8048431: 89 04 24 mov %eax,(%esp)
  14. 8048434: e8 9e ff ff ff call 80483d7
  15. 8048439: 83 ec 04 sub $0x4,%esp
  16. return_value local1 = my_test_pass(local);
  17. 804843c: 8d 45 c8 lea -0x38(%ebp),%eax
  18. 804843f: 8b 55 e0 mov -0x20(%ebp),%edx
  19. 8048442: 89 54 24 04 mov %edx,0x4(%esp)
  20. 8048446: 8b 55 e4 mov -0x1c(%ebp),%edx
  21. 8048449: 89 54 24 08 mov %edx,0x8(%esp)
  22. 804844d: 8b 55 e8 mov -0x18(%ebp),%edx
  23. 8048450: 89 54 24 0c mov %edx,0xc(%esp)
  24. 8048454: 8b 55 ec mov -0x14(%ebp),%edx
  25. 8048457: 89 54 24 10 mov %edx,0x10(%esp)
  26. 804845b: 8b 55 f0 mov -0x10(%ebp),%edx
  27. 804845e: 89 54 24 14 mov %edx,0x14(%esp)
  28. 8048462: 89 04 24 mov %eax,(%esp)
  29. 8048465: e8 2a ff ff ffcall8048394
  30. 804846a: 83 ec 04 sub $0x4,%esp
  31. return 0;
  32. 804846d: b8 00 00 00 00 mov $0x0,%eax
  33. }
...
由上面的反汇编代码可以知道结构体的传递参数是依据堆栈实现的。这也说明了多参数的传递过程并不是按着固定的模式实现的,这也是我们需要注意的问题。参数的传递需要根据实际情况分析。
总结:
函数的调用是有一定的方式的,各个函数都有一定的堆栈空间,而且每一个堆栈空间的分布情况也是类似的,但是大小要根据实际的情况分析。一般一个函数的堆栈空间中包含下面几个部分:1、栈帧(用来表示该堆栈空间的栈底,也就是指开始的地址EBP),局部变量的空间,下一个被调用函数的参数传递,最后是返回地址(实质上也是一个EBP)。就是依据EBP和相对位置就能知道每一个函数的基本分布,而ESP就能知道堆栈空间的大小。
被调用参数的获取主要是依据EBP指针的相对位置获得,因为被调用函数的堆栈空间上一个堆栈空间就是调用函数的堆栈空间。根据函数的栈帧指针(EBP)和相对位置(-4,-8等)找到对应的参数,但是相对位置也是不固定的,这需要考虑结构体的对齐等方式,具体的要在实际中计算。
返回值一般都是采用EAX返回的,但是对于结构体等则是采用堆栈的方式一个元算一个元素的返回的,但是还是运用了EAX的特性。
函数调用的分布打开如下:

从上面的分析我们可以发现汇编代码是非常有用的,建议多参看汇编代码分析具体的问题。
上一页 1 2 3 下一页

关键词:C语言函数调

评论


技术专区

关闭