C语言返回值深入研究
来源:互联网 发布:淘宝去边框代码 编辑:程序博客网 时间:2024/06/01 10:38
<span style="background-color: rgb(255, 255, 255); font-family: Arial, Helvetica, sans-serif;">转载于:http://nxlhero.blog.51cto.com/962631/703953</span>
int f() { return 100; } void main() { f(); }
//file:haha.cstruct xxx{ int a[50];};struct xxx main(){ struct xxx haha; return haha;}
<span style="color:#555555;">//示例1:返回值为char /*C代码*/char f(){ char a = 'a'; return a;}int main(){ char b = f(); return 0;}/*汇编代码*/ .file "char.c" .text .globl ff:pushl %ebpmovl %esp, %ebpsubl $16, %esp </span><span style="color:#ff6666;"> movb $97, -1(%ebp) movsbl -1(%ebp),%eax //符号扩展</span><span style="color:#555555;">leaveret.globl main main: leal 4(%esp), %ecx andl $-16, %esp pushl -4(%ecx) pushl %ebp movl %esp, %ebp pushl %ecx </span><span style="color:#ff6666;"> subl $16, %esp call f movb %al, -5(%ebp) </span><span style="color:#555555;"> movl $0, %eax addl $16, %esp popl %ecx popl %ebp leal -4(%ecx), %esp ret </span>
/*示例2:32位系统上返回64位整数*/ /*C代码*/ long long f() { long long a = 5; return a; } int main() { long long b; b=f(); return 0; } /*汇编代码*/ .file "longint.c" .text .globl f f: pushl %ebp movl %esp, %ebp subl $16, %esp movl $5, -8(%ebp) movl $0, -4(%ebp) <span style="color:#ff6666;">movl -8(%ebp), %eax movl -4(%ebp), %edx </span> leave ret .globl main main: leal 4(%esp), %ecx andl $-16, %esp pushl -4(%ecx) pushl %ebp movl %esp, %ebp pushl %ecx subl $20, %esp call f <span style="color:#ff6666;">movl %eax, -16(%ebp) movl %edx, -12(%ebp) </span> movl $0, %eax addl $20, %esp popl %ecx popl %ebp leal -4(%ecx), %esp ret
/*示例3:返回值为浮点数* /*C代码*/ float f() { return 0.1; } int main() { float a = f(); return 0; } /*汇编代码*/ .file "float.c" .text .globl f f: pushl %ebp movl %esp, %ebp subl $4, %esp movl $0x3dcccccd, %eax movl %eax, -4(%ebp) <span style="color:#ff6666;">flds -4(%ebp) //把结果压到浮点寄存器栈顶 </span> leave ret .globl main main: leal 4(%esp), %ecx andl $-16, %esp pushl -4(%ecx) pushl %ebp movl %esp, %ebp pushl %ecx subl $16, %esp call f <span style="color:#ff6666;">fstps -8(%ebp) //从浮点寄存器栈顶取数 </span> movl $0, %eax addl $16, %esp popl %ecx popl %ebp leal -4(%ecx), %esp ret
/*示例4:返回值为指针*/ /*C代码*/ int f() { return 5; } int (*whatisthis()) () //这个函数的返回类型是函数指针{ return f; } int main() { int (*a) (); int b; a = whatisthis(); b = a(); printf("%d\n",b); return 0; } /*汇编代码*/ .file "ret_fun.c" .text .globl f f: pushl %ebp movl %esp, %ebp movl $5, %eax popl %ebp ret .globl whatisthis whatisthis: pushl %ebp movl %esp, %ebp <span style="color:#ff6666;">movl $f, %eax </span> popl %ebp ret .LC0: .string "%d\n" .text .globl main main: leal 4(%esp), %ecx andl $-16, %esp pushl -4(%ecx) pushl %ebp movl %esp, %ebp pushl %ecx subl $36, %esp <span style="color:#ff6666;">call whatisthis movl %eax, -12(%ebp) movl -12(%ebp), %eax call *%eax </span> movl %eax, -8(%ebp) movl -8(%ebp), %eax movl %eax, 4(%esp) movl $.LC0, (%esp) call printf movl $0, %eax addl $36, %esp popl %ecx popl %ebp leal -4(%ecx), %esp ret
/*示例5:struct只有一个字节*/ /*C代码*/ struct xxx{ char a; }; struct xxx f() { struct xxx x; x.a = '9'; return x; } int main() { struct xxx y = f(); return 0; } /*汇编代码*/ .file "struct_char.c" .text .globl f f: pushl %ebp movl %esp, %ebp subl $16, %esp <span style="color:#ff6666;">movl 8(%ebp), %edx //取出地址,放入edx </span> movb $57, -1(%ebp) <span style="color:#ff6666;">movzbl -1(%ebp), %eax //'9'放到 al movb %al, (%edx) //将al内容写到edx指向的地址 </span> movl %edx, %eax leave ret $4 .globl main main: leal 4(%esp), %ecx andl $-16, %esp pushl -4(%ecx) pushl %ebp movl %esp, %ebp pushl %ecx subl $24, %esp <span style="color:#ff6666;">leal -21(%ebp), %eax //地址放到eax movl %eax, (%esp) //地址压入栈中 </span> call f <span style="color:#ff6666;">subl $4, %esp //没有取返回值的指令了 movzbl -21(%ebp), %eax//因为已经写到目的地址了 </span> movb %al, -5(%ebp) movl $0, %eax movl -4(%ebp), %ecx leave leal -4(%ecx), %esp ret我们再来看个复杂点的例子
<span style="color:#555555;">/*示例6: struct较大*/ /*C代码*/ struct xxx { char a[10]; }; struct xxx f(int a) { struct xxx t; t.a[9] = 1; return t; } int main() { struct xxx m=f(1); return 0; } /*汇编代码*/ .file "struct.c" .text .globl f f: pushl %ebp movl %esp, %ebp subl $16, %esp </span><span style="color:#ff6666;"> movl 8(%ebp), %edx //取地址</span><span style="color:#555555;"> movb $1, -1(%ebp) movl -10(%ebp), %eax movl %eax, (%edx) movl -6(%ebp), %eax movl %eax, 4(%edx) movzwl -2(%ebp), %eax movw %ax, 8(%edx) movl %edx, %eax leave ret $4 .globl main main: leal 4(%esp), %ecx andl $-16, %esp pushl -4(%ecx) pushl %ebp movl %esp, %ebp pushl %ecx subl $24, %esp leal -14(%ebp), %eax </span><span style="color:#ff6666;"> movl $1, 4(%esp) //先压入参数 movl %eax, (%esp) //再压入返回值地址 </span><span style="color:#555555;"> call f subl $4, %esp movl $0, %eax movl -4(%ebp), %ecx leave leal -4(%ecx), %esp ret </span>进入被调用函数后的堆栈情况
struct xxx { char a[10]; }; struct xxx f(int a) { struct xxx t; t.a[9] = 1; return t; } int main() { f(1); return 0; }
int main() { int a; long long a1; double a2; a = {int b = 5; printf("xxx\n");;}; a1 = {int b = 5;int c = 2; 3-4;b-c;}; a2 = {int b = 5;int c = 2; 10-8;}; printf("%d\n",a); printf("%ld\n",a1); printf("%lf\n",a2); return 0; }上面代码中的3-4会被忽略,因为没有用,而10-8不会被忽略,因为它在代码块最后,但是不是执行sub指令,直接movl $2, %eax;
0 0
- C语言返回值深入研究
- 深入C语言返回值
- <C语言>关于函数返回值是指针,取不到值的问题研究
- tc2.0环境下的C语言研究-变量与参数返回值
- 7月16日|C语言|volatile用法及static用法及printf返回值研究
- C:深入研究MessageBox
- 形式参数和返回值的问题深入研究
- 形式参数和返回值的问题深入研究
- 028、形式参数和返回值的问题深入研究
- c语言scanf返回值
- c语言scanf返回值
- C语言返回值详解
- 开始研究C语言
- c语言函数返回值问题
- C语言函数返回值的获取
- 细谈C语言中的main返回值
- C语言函数说明与返回值
- 细谈C语言中的main返回值 .
- 你是否浪费了你手中的数据?
- IOS KeyChain
- 接口与抽象类的区别
- HDU 4634 Swipe Bo
- 第十七周项目 3 胖子伤不起
- C语言返回值深入研究
- hdu4502临时工计划(01背包)
- OnCreate()和PreCreateWindow()函数的区别
- 数据控件中session传值的使用实例
- 10.1.2.1 C# 和 F# 中可重用的记忆化
- Java如何判断线程池所有任务是否执行完毕
- 默认参数python
- 黑马程序员 Java基础学习之GUI
- 根据DEDE自制报名系统(有后台和权限)