用汇编看c++中的类型转换

来源:互联网 发布:微盘,南风知我意 编辑:程序博客网 时间:2024/06/05 19:57

c++的类型转换机制,基本所有书上都有若干规则.这些规则很多,很难记.实际上类型转换机制和汇编代码表示是分不开的.本文主要从汇编代码的角度重新观察和解读c++的类型转换机制.

首先,我们看看cplusplus 对类型转换的阐述:

1. 标准转换(standard conversion)指算术类型间的转换,以及算术类型和一些指针类型的转换.

   其中,较小的整型到int以及floatdouble的转换成为类型提升(promotion),它们不会导致精度损失.其他转换可能导致精度损失,举例如下:

          负整型值转换为无符号整型,结果会是正的大整型数;

          非0数转换为bool型结果为1,非NULL指针转换为bool型结果为1;

          浮点数转换为整型数会导致截断(truncated),如果转换结果在整型数表示范围外,那么转换导致为定义行为(undefined behavior);

          其他整型和整型,浮点型和浮点型的转换是正确的,然而结果与实现相关,也可能不可移植.


   2.  数组和函数可以转换为指针;NULL可以转换为任意指针;任意指针可以转换为void指针;子类指针可以转换为父类指针.


关于类的隐式转换就不再阐述了.接下来就看看几个例子,贴出汇编代码来解读.

short a, b; cin >> a >> b; short c = a + b;

汇编代码如下(忽略cin >> a >> b):

<span style="font-family:Verdana;">00232F61  movsx       eax,word ptr [a] 00232F68  movsx       ecx,word ptr [b] 00232F6F  add           eax,ecx 00232F71  mov          word ptr [c],ax </span>

ab载入的都是32位寄存器,相加后截断存入c.结论就是c++的小于int的整型加法都是转换为int再计算的.


double a; char b; cin >> a >> b; double c = a + b; 

汇编如下:

00BF2EF5  movsx       eax,byte ptr [b] 00BF2EFC  mov          dword ptr [ebp-30Ch],eax 00BF2F02  fild            dword ptr [ebp-30Ch] 00BF2F08  fadd          qword ptr [a] 00BF2F0E  fstp           qword ptr [c] 

movsx指令为带符号扩展并传送.b先转换为int,将双字存入内存,通过fild转换为double载入浮点协处理器.接下来就是浮点协处理器执行加法操作并存入c. 结论就是:小于int的整型和浮点数相加,先转换为int(如果是无符号数则使用movzx指令),再转换为浮点数(小于等于32位的整型数使用fild dword,64位整型数使用fild qword).


位操作也有类似原理.小于32位的整型转换为int(无符号转换为unsigned)再进行位运算,64位整型则是分别对低32位和高32位进行位运算.

下面是一个有趣的对比:

unsigned a = 1; int b = -1; if(a > b) cout << "aaa" << endl;int a = 1; int b = -1; if(a > b) cout << "aaa" << endl;

第一行汇编如下:

00E430A2  mov         dword ptr [a],1 00E430AC  mov         dword ptr [b],0FFFFFFFFh 00E430B6  mov         eax,dword ptr [a] 00E430BC  cmp         eax,dword ptr [b] 00E430C2  jbe         00E430EF 

比较大小使用的是jbe.

第二行汇编如下:

00E430EF  mov         dword ptr [a],1 00E430F9  mov         dword ptr [b],0FFFFFFFFh 00E43103  mov         eax,dword ptr [a] 00E43109  cmp         eax,dword ptr [b] 00E4310F  jle         00E4313C 

比较大小使用的是jle.前4行汇编代码完全一致,只是通过汇编中的"有符号跳转"和"无符号跳转"的区别区分.


通过对几段汇编代码的分析,认识c++的类型转换规则更加深刻了.固然,类型转换规则的内容有与机器无关的考虑在内,但也肯定与数据的机器级表示以及指令集有密切关联.



 

0 0
原创粉丝点击