正如前文所说,函数返回值会被存入EAX等寄存器,然后返回后由程序从中读取。但如果返回值较大呢?
开始博主打算用double测试,后来发现这个要用到x87这套完全不同的指令集。只好用结构体了。构造C程序
#include <stdio.h> struct myrd{ int i; int j; int k; }; struct myrd myrdfunc(){ struct myrd myrd1; myrd1.i = 1; myrd1.j = 2; myrd1.k = 3; return myrd1; } int main(){ struct myrd myrd2; myrd2 = myrdfunc(); }
在两个函数入口处设置断电。在myrdfunc()入口处(call语句前)可看到
00BB36E8 8D 85 18 FF FF FF lea eax,[ebp+FFFFFF18h] 00BB36EE 50 push eax
由此可见为了返回专门开辟了一块内存区域并将地址存入了EAX。记录EAX的值。进入函数。观察该段
00BB3CDD 8B 45 08 mov eax,dword ptr [ebp+8] 00BB3CE0 8B 4D EC mov ecx,dword ptr [ebp-14h] 00BB3CE3 89 08 mov dword ptr [eax],ecx 00BB3CE5 8B 55 F0 mov edx,dword ptr [ebp-10h] 00BB3CE8 89 50 04 mov dword ptr [eax+4],edx 00BB3CEB 8B 4D F4 mov ecx,dword ptr [ebp-0Ch] 00BB3CEE 89 48 08 mov dword ptr [eax+8],ecx 00BB3CF1 8B 45 08 mov eax,dword ptr [ebp+8]
检查ebp+8的值,恰为eax。而通过ecx,edx将三个值分别存到eax所指向的内存区域。最后将ebp+8的值重新复制给eax。之后函数返回。
跳转回main后第一条语句为
00BB36F4 83 C4 04 add esp,4
观察esp+4的值,恰为刚才压入栈中的eax,此操作将清栈。
之后便是从eax中取回函数的返回值。
00BB36F7 8B 08 mov ecx,dword ptr [eax] 00BB36F9 89 4D EC mov dword ptr [ebp-14h],ecx 00BB36FC 8B 50 04 mov edx,dword ptr [eax+4] 00BB36FF 89 55 F0 mov dword ptr [ebp-10h],edx 00BB3702 8B 40 08 mov eax,dword ptr [eax+8] 00BB3705 89 45 F4 mov dword ptr [ebp-0Ch],eax
由于main中没有其他操作,而局部变量的生存期又很短,我们猜想这些代码是不是冗余呢?
将debug改为release
此时debug:
生成程序只有两行,没有任何冗余。由此可见debug和release程序的用途完全不同。
时间: 2024-10-19 17:11:07