G ++生成逻辑上错误的汇编代码

Dou*_*haw 1 c++ g++ real-mode

今天我使用g ++来编译一个c ++文件,但是g ++似乎有一个问题,当一个char类型的变量与任意数量的char类型比较,并且第7位设置为1时,g ++总是假设它是假的因此使得这些东西错误.更具体地说,c ++代码如下所示:

  // test.cpp
    __asm__(".code16gcc \n\t");
    int equals0(char i)
    {
        return i==0x80;
    }
    int equals1(char i)
    {
        return i==0x10;
    }
    int equals2(int i)
    {
        return i==0x80;
    }
Run Code Online (Sandbox Code Playgroud)

请注意,有一个前导句".code16gcc",我用它来生成实模式代码.

更具体地说,我的g ++版本是cygwin上的"g ++(GCC)6.4.0".

现在,使用以下命令将此文件编译为汇编代码 g++ -S -o test.s test.cpp -m32

结果文件是:

     // some trival information is omitted
    .code16gcc 

    .text
    ...
__Z7equals0c://func equals0
    pushl   %ebp
    movl    %esp, %ebp
    subl    $4, %esp
    movl    8(%ebp), %eax
    movb    %al, -4(%ebp)  //no comparison with 0x80 
    movl    $0, %eax   //always returns 0
    leave
    ret
    ...
__Z7equals1c://func equals1
    pushl   %ebp
    movl    %esp, %ebp
    subl    $4, %esp
    movl    8(%ebp), %eax
    movb    %al, -4(%ebp)
    cmpb    $16, -4(%ebp)  // a comparison with 0x10
    sete    %al
    movzbl  %al, %eax    // returns value depend on the result of comparison
    leave
    ret
    ...
__Z7equals2i://func equals2
    pushl   %ebp
    movl    %esp, %ebp
    cmpl    $128, 8(%ebp) //also a comparison
    sete    %al
    movzbl  %al, %eax
    popl    %ebp
    ret
Run Code Online (Sandbox Code Playgroud)

请注意,函数equals0将始终返回0(保存在eax中),但函数equals1将根据生成的程序集文件返回正确的结果.

并且还要注意,函数equals0和equals1之间的唯一区别是用于比较的常量,对于equals0为0x80,对于equals1为0x10.基于此,我们可以说g ++已生成逻辑上错误的代码.

谁知道为什么会解释这个?

Jar*_*d42 8

0x80(int 128)超出了signed char([-128;127])的范围.

所以签名的字母不能等于 0x80