当 x 是 uint8 时 x |= 128 的好奇 gcc 编译器代码
curious gcc compiler code for x |= 128 when x is uint8
我最近偶然发现了一个我不理解的有趣的编译器代码。
取以下代码:
unsigned char x;
...
x |= 127;
x |= 128;
对于第一条语句,编译器生成:
or eax, 0x7f.
然而,对于第二个语句,它变成:
or eax, 0xffffff80
似乎对于小于 127 的值,使用一个字节值,而在 128 个双字之后是首选。
有人知道为什么会这样吗?
我转载了这个 gcc 6.2(我认为是最新的)。
我试图 post 在 gcc 邮件列表(gcc-bugs@gcc.gnu.org 或 gcc-help@gcc.gnu.org )上,但我只收到了发送失败。
两条指令都是 3 字节宽,从反汇编输出中可以看出:
83 c8 7f or [=10=]x7f,%eax
83 c8 80 or [=10=]xffffff80,%eax
83 / 1 是 32-bit register / memory with 8-bit sign-extended immediate value:
83 /1 ib OR r/m32,imm8 r/m32 OR imm8 (sign-extended).
因此实际上它确实改变了 32 位寄存器的不可见部分,但这并不重要。它的效率不低于任何其他方法。除了那些使用 8 位寄存器 halves/quarters 操作的指令外,也没有指令 不会 对 8 位立即值进行符号扩展。但是使用这条指令使得它与其他寄存器的工作方式相同,这些寄存器可以用 r/m32
寻址但不能作为单个字节访问(例如 edi、esi)。
我最近偶然发现了一个我不理解的有趣的编译器代码。 取以下代码:
unsigned char x;
...
x |= 127;
x |= 128;
对于第一条语句,编译器生成:
or eax, 0x7f.
然而,对于第二个语句,它变成:
or eax, 0xffffff80
似乎对于小于 127 的值,使用一个字节值,而在 128 个双字之后是首选。
有人知道为什么会这样吗? 我转载了这个 gcc 6.2(我认为是最新的)。
我试图 post 在 gcc 邮件列表(gcc-bugs@gcc.gnu.org 或 gcc-help@gcc.gnu.org )上,但我只收到了发送失败。
两条指令都是 3 字节宽,从反汇编输出中可以看出:
83 c8 7f or [=10=]x7f,%eax
83 c8 80 or [=10=]xffffff80,%eax
83 / 1 是 32-bit register / memory with 8-bit sign-extended immediate value:
83 /1 ib OR r/m32,imm8 r/m32 OR imm8 (sign-extended).
因此实际上它确实改变了 32 位寄存器的不可见部分,但这并不重要。它的效率不低于任何其他方法。除了那些使用 8 位寄存器 halves/quarters 操作的指令外,也没有指令 不会 对 8 位立即值进行符号扩展。但是使用这条指令使得它与其他寄存器的工作方式相同,这些寄存器可以用 r/m32
寻址但不能作为单个字节访问(例如 edi、esi)。