今天周老师在群里发了一段代码,如下:
- 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:不清楚自己分析的对不对,欢迎各路神仙留言指正。