zoukankan      html  css  js  c++  java
  • 代码中的隐式转换问题

    今天在调试代码的时候,碰到一个很奇怪的现象,一条简单的语句,执行结果就是不对。

    代码如下

    int pack_size = recbuffer[1] + (rec_buffer_[0] << 8)

    其中recbuffer为char类型,recbuffer[1]的值是0xd6,recbuffer[0]的值是0x01,预期的结果pack_size应为0x01d6。

    根据c++的算术运算隐式转换规则,recbuffer[1]和recbuffer[0]都会被提升为整型,pack_size = 0xd6 + 0x100, 而实际执行结果确是0xd6。令我百思不得其解。

    实在是没办法,将代码拆分为如下:

    int pack_size = rec_buffer_[0];
    
    pack_size <<= 8;
    
    pack_size += rec_buffer_[1];

    结果依然一样,还是0xd6,单步跟踪后,发现在pack_size+=recbuffer[1]这里,pack_size += rec_buffer_[1]执行后,pack_size从0x100变为0xd6,高位居然丢失了!

    没办法,转到汇编,得到如下代码:

    int pack_size = rec_buffer_[0];
    01422A2A  mov         eax,dword ptr [ebp-14h]  
    01422A2D  movsx       ecx,byte ptr [eax+71h]  
    01422A31  mov         dword ptr [pack_size],ecx  
    pack_size <<= 8;
    01422A34  mov         eax,dword ptr [pack_size]  
    01422A37  shl         eax,8  
    01422A3A  mov         dword ptr [pack_size],eax  
    pack_size += rec_buffer_[1];
    01422A3D  mov         eax,dword ptr [ebp-14h]  
    01422A40  movsx       ecx,byte ptr [eax+72h]  
    01422A44  add         ecx,dword ptr [pack_size]  
    01422A47  mov         dword ptr [pack_size],ecx  

    终于看到问题所在了,在将recbuffer[1]提升为int类型时,编译器使用了movsx指令,而movsx的含义是:

    MOVSX说明:带符号扩展传送指令
      符号扩展的意思是,当计算机存储某一个有符号数时,符号位位于该数的第一位,所以,当扩展一个负数的时候需要将扩展的高位全赋为1.对于正数而言,符号扩展和零扩展MOVZX是一样的,将扩展的高位全赋为0.

    也即0xd6经过提升为整型后变为0xffffffd6,加上0x100后,正好变成0xd6,造成了高位丢失的假象!

    原来问题在于recbuffer的类型为char,这里0xd6是一个负数,将其修改为uchar后,恢复正常。看来在今后的代码中对于类型声明还是要多加注意。

    也怪我在调试器中一直将数值显示改为16进制类型,如果显示为10进制,早早可以看到d6是个负数,也不会如此大费周章了。

  • 相关阅读:
    What does the LayoutAwarePage Class provide
    UML类图几种关系的总结
    WriteableBitmap 巧学巧用
    iOS图片填充UIImageView(contentMode)
    UIImage扩展用代码直接改变图片大小
    iOS各框架功能简述以及系统层次结构简单分析
    【深拷贝VS浅拷贝】
    【node】node连接mongodb操作数据库
    【node】mongoose的基本使用
    【node】websocket
  • 原文地址:https://www.cnblogs.com/hotzenplotz/p/2921261.html
Copyright © 2011-2022 走看看