一般情况下,函数返回值是通过eax进行传递的,但是eax只能存储4个字节的信息,对于那些返回值大于4个字节的函数,返回值是如何传递的呢?
假设返回值大小为M字节
1. M <= 4字节,放入eax返回
2. 4 < M <=8,把eax,edx联合起来,其中,edx存储高位,eax存储低位
3. M > 8,如何传递呢?
测试代码:
//test.cpp
如上,test()函数的返回值大小为64字节,那它是如何将这个大小的返回值传递给函数调用者的呢?
g++ -S test.cpp
查看汇编代码,如下:
其中:符号_Z4testv,用c++filt查看可知为test()。
先看看main函数的汇编代码:
pushl %ecx //将ecx的值压栈
subl $68, %esp //栈中分配68字节的空间,可以将这个空间看成两部分,一部分64字节是为变量n分配的空间,另一部分暂不考虑
此时main函数栈的情况如下:
leal -68(%ebp), %eax //将%ebp - 68字节处的值传到eax中,也就是4(%esp)处,也就是变量n的起始地址
movl %eax, (%esp) //将eax值,也就是变量n的起始地址,放入栈的%esp处,也就是上面分配的68字节空间的第二部分
call _Z4testv //调用函数 test()
看看函数test的汇编代码:
subl $64, %esp //为变量big分配64字节的空间
movl 8(%ebp), %eax //将%ebp + 8 字节处的值,也就是main函数中分配的68字节的第二部分的值,
也就是main中变量n的起始地址的值,存入eax中
movb $99, 1(%eax) //将99也就是'c'的ascii值放入%eax + 1字节处,而刚才说了eax中的值是变量n的其实地址,
所以这一步就相当于直接改变了变量n的值,从而实现了函数test的返回值到调用函数的传递。
如果将代码test.cpp中的:
big_thing n = test();
改成:
test();
汇编代码有什么变化,在main函数的栈中还会为test函数的返回值准备空间吗,但是现在main函数现在并不想接受test的返回值呀~
比较一下汇编代码你就知道啦,呵呵
(汇编代码没有任何变化,编译器还是在main的栈中为其分配了空间)