今天我使用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 ++已生成逻辑上错误的代码.
谁知道为什么会解释这个?