近来在写程序的时候遇到一个问题,由于平时比较忙,也都没仔细想过不同数据类型相加的问题,特别是有符号和无符号相加的问题,结果在输出结果的时候发现总是不对,后来仔细问题才发现问题所在,这里写出来以供大家学习参考.
问题如下:
已知
char *pData = buf[3];
pData[0] = 0x03;
pDatap1] = 0xe8;
unsigned short src_port = (pData[0]
<< 8) + (USHORT)pData[1];
问src_port的结果是多少?
我们可以用VC产生的汇编看看:
1.原等式
unsigned short src_port = (pData[0]
<< 8) + (USHORT)pData[1];
00401AEE mov eax,dword ptr [ebp-14h]
00401AF1 movsx ecx,byte ptr [eax]/** ①注意到这里没有 **/
00401AF4 shl ecx,8
00401AF7 mov edx,dword ptr [ebp-14h]
00401AFA movsx eax,byte ptr [edx+1]
00401AFE add ecx,eax
00401B00 mov word ptr [src_port],cx
2.使用0xe8代替pData[1]
unsigned short src_port = (pData[0]
<< 8) + 0xe8;
00401AEE mov eax,dword ptr [ebp-14h]
00401AF1 movsx ecx,byte ptr [eax]/** ②注意到这里没有 **/
00401AF4 shl ecx,8
00401AF7 add ecx,0E8h
00401AFD mov word ptr [src_port],cx
猜猜看上面的两个结果是什么?
1.0x02e8
2.0x03e8
让我们来改个写法来看看结果:
3.把pdata修改为unsigned:
unsigned char *pData =
buf[3];
看看产生的汇编:
464: unsigned
short src_port = (pData[0] << 8) + pData[1];;
00410AFF mov eax,dword ptr [ebp-14h]
00410B02 xor ecx,ecx
00410B04 mov cl,byte ptr [eax]/** ③注意到这里没有 **/
00410B06 shl ecx,8
00410B09 mov edx,dword ptr [ebp-14h]
00410B0C xor eax,eax
00410B0E mov al,byte ptr [edx+1]
00410B11 add ecx,eax
00410B13 mov word ptr [src_port],cx
我想细心的人已经注意到了我给的标注①②③,仔细对比它们的意思,我们可以发现,对于有符号和无符号的取值产生的汇编是不一样,而就是由于取值的不同,就会导致输出的不同,而其中的关键其实就是有符号-->无符号的转换.
这里的转换是字节byte ptr
[eax](pdata[0]的值)-->ecx(32位)的转换,而这种转换存在隐式规则,当符号位为1时,转换为多字节后,高位字节补为全1,即0xe8
-->
0xffffff88.那么我们就可以知道1、2问题的计算结果是如何得来的了:
1。 0x0300 + 0xffe8 = 0x02e8
2. 0x0300 + 0x00e8 = 0x03e8
在这里还涉及到读汇编代码时的一些积存器的意思,下面简单附一些解释:
32位汇编使用EAX,EBX,ECX,EDX寄存器,但是兼容16位的寄存器,即对应AX,BX,CX,DX,AL,BL,CL,DL,AH,BH,CH,DH.
比如说,当你想改变EAX的低8个bit时,只需要改变AL就可以.