我们学过汇编的都应该知道C语言的返回值,在x86机器上面都是用eax来实现的。而eax是32位的,所以返回值只能是int/long类型或者指针类型,在汇编里面都是dword。可是突然想到怎么实现返回64位值呢?难道会是指针?显然不太可能这样做。
MSVC
返回double
实际上我们来试一下就知道了。
|
执行Cl /Fa a.c
|
我们可以发现实际上是利用的X87的ST(0)栈寄存器来传递的,然后编译器自动在call语句后面加了一句fstp来从X87里面取出来。
返回 long long
我们再来看看longlong的。
|
汇编代码
|
这里返回前call了一个__dtol3的函数,从main里面我们可以看到long long值是被它转到了eax edx里面去了。s虽然我们不知道这个dtol3干啥用的,但是它作用应该是清晰的,从xmm0取出64位整数,放到eax edx中。 所以返回64位整数是用的eax 和edx来做的。
返回结构体呢?也可以类似分析,只是代码比较多。这里就不贴出来了。看VC++实现的是caller预分配自己栈空间,通过lea eax, DWORD PTR $T1[ebp]; push eax; call _test; add esp, 4
传入一个buffer来让callee填。
然后我们来看看gcc和clang是怎么处理的吧!
gcc
下面是gcc3.4.4的结果
double
|
long long
double的
|
可以发现gcc的代码直白很多,没有msvc的那种负担,但是二进制代码和汇编代码好像还不完全一样,最终代码似乎并没有完全按照他编译出来的汇编翻译,应该是还有后续的优化过程。之所以我不贴gcc4.9的代码,是因为它优化比较厉害,直接函数都不调用了。
clang
下面是clang 3.4.2
double
|
long long
double的
|