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是个负数,也不会如此大费周章了。

  • 相关阅读:
    Hive_元数据配置到MySQL
    第一篇
    mysql查询结果添加序列号
    java中正则表达式
    java位运算
    正数负数原码,反码,补码
    各进制间相互转换
    linux下默认安装jdk路径查找
    localhost:8080/manager/status无法访问403 Access Denied
    Idea官网指南
  • 原文地址:https://www.cnblogs.com/hotzenplotz/p/2921261.html
Copyright © 2011-2022 走看看