今天周老师在群里发了一段代码,如下:
int _tmain(int argc, _TCHAR* argv[])
{
int i = 15;
float m = (float)i;
printf("%d\n",m);
return 0;
}
并告知输出为0, 运行并且如此。查看反汇编代码如下
int _tmain(int argc, _TCHAR* argv[])
{
00F51000 55 push ebp
00F51001 8B EC mov ebp,esp
00F51003 83 EC 08 sub esp,8
int i = 15;
00F51006 C7 45 FC 0F 00 00 00 mov dword ptr [i],0Fh
float m = (float)i;
00F5100D DB 45 FC fild dword ptr [i]
00F51010 D9 5D F8 fstp dword ptr [m]
printf("%d\n",m);
00F51013 D9 45 F8 fld dword ptr [m]
00F51016 83 EC 08 sub esp,8
00F51019 DD 1C 24 fstp qword ptr [esp]
00F5101C 68 F4 20 F5 00 push offset ___xi_z+34h (0F520F4h)
00F51021 FF 15 A0 20 F5 00 call dword ptr [__imp__printf (0F520A0h)]
00F51027 83 C4 0C add esp,0Ch
return 0;
00F5102A 33 C0 xor eax,eax
}
00F5102C 8B E5 mov esp,ebp
00F5102E 5D pop ebp
00F5102F C3 ret
请注意标红的两句,明明传递的float类型,怎么需要八个字节呢? 莫非传递float类型就是这样吗?于是我又写了个测试子函数
#include "stdafx.h"
float fun(float f)
{
return f+1;
}
int _tmain(int argc, _TCHAR* argv[])
{
int i = 15;
float m = (float)i;
float y = fun(m);
printf("%d\n",m);
return 0;
}
其对应的反汇编代码为
int _tmain(int argc, _TCHAR* argv[])
{
00B71020 55 push ebp
00B71021 8B EC mov ebp,esp
00B71023 83 EC 0C sub esp,0Ch
int i = 15;
00B71026 C7 45 F8 0F 00 00 00 mov dword ptr [i],0Fh
float m = (float)i;
00B7102D DB 45 F8 fild dword ptr [i]
00B71030 D9 5D F4 fstp dword ptr [m]
float y = fun(m);
00B71033 51 push ecx
00B71034 D9 45 F4 fld dword ptr [m]
00B71037 D9 1C 24 fstp dword ptr [esp]
00B7103A E8 C1 FF FF FF call fun (0B71000h)
00B7103F 83 C4 04 add esp,4
00B71042 D9 5D FC fstp dword ptr [y]
printf("%d\n",m);
00B71045 D9 45 F4 fld dword ptr [m]
00B71048 83 EC 08 sub esp,8
00B7104B DD 1C 24 fstp qword ptr [esp]
00B7104E 68 F4 20 B7 00 push offset ___xi_z+34h (0B720F4h)
00B71053 FF 15 A0 20 B7 00 call dword ptr [__imp__printf (0B720A0h)]
00B71059 83 C4 0C add esp,0Ch
return 0;
00B7105C 33 C0 xor eax,eax
}
00B7105E 8B E5 mov esp,ebp
00B71060 5D pop ebp
00B71061 C3 ret
请注意标红的汇编代码,调用fun函数时传递float类型使用了4字节,这才符合预期,但是调用printf时为何传递的8字节呢?终于baidu到这么一句话:
浮点数作为变参函数的参数时需要转换为双精度浮点值
这才揭晓了原因,原来float作为变参函数的参数需要转换为双精度浮点值(重要的话重复3遍)。
知道了这些,就不难理解本文开头的程序输出为0了, float (15) 转成双精度浮点数后,高位4字节为0,且此高4位和%d对应,故输出为0.
PS:不清楚自己分析的对不对,欢迎各路神仙留言指正。