为什么gcc总是生成jle / jg?

时间:2015-08-07 15:44:05

标签: gcc optimization assembly

我制作一些只与字符比较的汇编测试代码, gcc使jle / jg组合总是条件是否包含相等。

示例1。

if('A'< test&& test<'Z')

function inventoryAdd() {
    // ...custom function stuff... 
}

function onEdit(event) {
    inventoryAdd();
}

示例2。

if('A'< = test&& test< ='Z')

0x000000000040054d <+32>:   cmp    BYTE PTR [rbp-0x1],0x41

0x0000000000400551 <+36>:   jle    0x40056a <main+61>

0x0000000000400553 <+38>:   cmp    BYTE PTR [rbp-0x1],0x59

0x0000000000400557 <+42>:   jg     0x40056a <main+61>

我认为这是关于优化的问题,但即使我使用-O0选项进行编译,GCC也会给出相同的结果。

如何通过'A'&lt; JL获得JL / JG? sth&lt;'Z'和JLE / JGE通过'A'&lt; = sth&lt; ='Z'?

2 个答案:

答案 0 :(得分:2)

可以看出第一次比较是针对[x41 ... x59]范围的。第二次比较是针对[x40 ... x5a]范围。基本上,编译器进入

if ( 'A'-1 < test && test < 'Z'+1 )

然后生成相同的代码

更新

为了弄清楚为什么我认为编译器更喜欢JL和JLE。 JLE依赖于更新的标志值(ZF = 1),但JL不会。因此,即使指令时序本身相同,JLE也会引入可能会损害指令级并行性的依赖性

因此,明确选择 - 转换代码以使用更简单的指令。

答案 1 :(得分:1)

通常,您不能强制编译器发出特定指令。在这种情况下,如果您删除常量,则可能会成功,因此编译器无法对其进行调整。请注意,由于表达式的性质,编译器可能仍会反转其中一个测试,从而引入等于。您可以使用goto来解决这个问题。显然,这两种变化都会产生更糟糕的代码。