当x是uint8时,x | = 128的好奇gcc编译器代码

Ste*_*hai 2 c assembly gcc cpu-registers compiler-optimization

我最近偶然发现了一个我不理解的有趣的编译器代码.请使用以下代码:

unsigned char x;
...
x |= 127;
x |= 128;
Run Code Online (Sandbox Code Playgroud)

对于第一个语句,编译器生成:

or eax, 0x7f.
Run Code Online (Sandbox Code Playgroud)

但是,对于第二个陈述,它变为:

or eax, 0xffffff80
Run Code Online (Sandbox Code Playgroud)

似乎对于小于127的值,使用一个字节值,而在128个dword之后是优选的.

有没有人知道为什么会这样?我转载了这个gcc 6.2(我认为是最新的).

我试图在gcc邮件列表(gcc-bugs@gcc.gnu.org或gcc-help@gcc.gnu.org)上发帖,但我只是发送失败.

Ant*_*ala 5

这两条指令都是3字节宽,从反汇编输出可以看出:

 83 c8 7f                or     $0x7f,%eax
 83 c8 80                or     $0xffffff80,%eax
Run Code Online (Sandbox Code Playgroud)

83/1是32位寄存器/存储器,具有8位符号扩展立即值:

83 /1 ib    OR r/m32,imm8   r/m32 OR imm8 (sign-extended).
Run Code Online (Sandbox Code Playgroud)

因此实际上它确实改变了32位寄存器的不可见部分,但这并不重要.它的效率不比任何其他方法低.除了那些以8位寄存器半/四分之一运行的指令外,还没有指令不会对8位立即值进行符号扩展.但是使用该指令使其与其他可寻址r/m32但无法作为单个字节访问的寄存器(例如edi,esi)的工作方式相同.