LinuxSir.cn,穿越时空的Linuxsir!

 找回密码
 注册
搜索
热搜: shell linux mysql
查看: 916|回复: 3

C 中返回结构类型变量的讨论

[复制链接]
发表于 2006-9-18 18:17:07 | 显示全部楼层 |阅读模式
最近我在尝试写 Emacs 的扩展,用 C 完成。读过 Emacs 的源代码后发现,其中存在大量返回结构(或联合)类型的变量的函数。对此我不是很懂,遂用 GCC 试验了一下。如下代码:
  1. #include <stdio.h>   

  2. struct abc  
  3. {        
  4.   int x, y, z;
  5. };

  6. struct abc func1 (void)
  7. {        
  8.   struct abc r;

  9.   r.x = 8, r.y = 7, r.z = 6;
  10.   return r;
  11. }
  12.      
  13. void func2 (struct abc v)
  14. {
  15.   printf ("%d\n%d\n%d\n", v.x, v.y, v.z);
  16. }

  17. int main (int argc, char *argv[])
  18. {
  19.   func2 (func1 ());
  20.   return 0;
  21. }
复制代码

func1 将被编译为
  1. func1:
  2.         pushl %ebp
  3.         movl %esp,%ebp
  4.         subl $24,%esp
  5. [color="Red"]        movl 8(%ebp),%eax[/color]
  6.         movl $8,-12(%ebp)
  7.         movl $7,-8(%ebp)
  8.         movl $6,-4(%ebp)
  9.         movl -12(%ebp),%edx
  10. [color="Red"]        movl %edx,(%eax)[/color]
  11.         movl -8(%ebp),%edx  
  12. [color="red"]        movl %edx,4(%eax)[/color]
  13.         movl -4(%ebp),%edx
  14. [color="red"]        movl %edx,8(%eax)[/color]
  15.         jmp .L6
  16. .L6:
  17.         movl %eax,%eax
  18.         leave
  19.         ret $4
复制代码

其对应的调用处被编译为
  1. [color="red"]        leal -12(%ebp),%eax[/color]
  2.         addl $-12,%esp
  3. [color="red"]        pushl %eax[/color]
  4.         call func1
  5.         addl $12,%esp
复制代码

从红色的部分可以看到,func1 是直接将要返回的值写入到了调用者的堆栈中。

有两点我不明白的地方:

1. movl %eax,%eax 的作用是什么?

2. 其他编译器是否也这样做?

欢迎就此展开讨论。
发表于 2006-9-18 18:28:43 | 显示全部楼层
  1. func1:
  2.         pushl   %ebp
  3.         movl    %esp, %ebp
  4.         subl    $24, %esp
  5.         movl    8(%ebp), %edx
  6.         movl    $8, -24(%ebp)
  7.         movl    $7, -20(%ebp)
  8.         movl    $6, -16(%ebp)
  9.         movl    -24(%ebp), %eax
  10.         movl    %eax, (%edx)
  11.         movl    -20(%ebp), %eax
  12.         movl    %eax, 4(%edx)
  13.         movl    -16(%ebp), %eax
  14.         movl    %eax, 8(%edx)
  15.         movl    %edx, %eax
  16.         leave
  17.         ret     $4
复制代码
  1. [rick@Fedora-Core ~]$ gcc -v
  2. Reading specs from /usr/lib/gcc/i386-redhat-linux/3.4.2/specs
  3. Configured with: ../configure --prefix=/usr --mandir=/usr/share/man --infodir=/usr/share/info --enable-shared --enable-threads=posix --disable-checking --with-system-zlib --enable-__cxa_atexit --disable-libunwind-exceptions --enable-java-awt=gtk --host=i386-redhat-linux
  4. Thread model: posix
  5. gcc version 3.4.2 20041017 (Red Hat 3.4.2-6.fc3)
复制代码
回复 支持 反对

使用道具 举报

 楼主| 发表于 2006-9-18 18:36:49 | 显示全部楼层
rickxbx 能不能解释一下 movl 8(%ebp), %edx 中加 8 而不是 4 的原因?是不是 call func1 也在栈上填了一个字节的空间?谢谢。
回复 支持 反对

使用道具 举报

发表于 2006-9-18 18:49:23 | 显示全部楼层
the stack is as follows:

args
ret_addr
old-ebp          <------  now ebp points here

so......
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

快速回复 返回顶部 返回列表