繁体   English   中英

为什么总是gcc使jle / jg?

[英]why always gcc makes jle/jg?

我编写了一些仅与字符进行比较的汇编测试代码,无论条件是否相等,gcc总是使jle / jg组合。


范例1。

如果('A'<测试&&测试<'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>

范例2。

如果('A'<=测试&&测试<='Z')

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

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

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

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

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

如何通过'A'<sth <'Z'获得JL / JG,如何通过'A'<= sth <='Z'获得JLE / JGE?

可以看到,第一个比较是在[x41 ... x59]范围内。 第二个比较是针对[x40 ... x5a]范围。 基本上,编译器使其成为

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

然后生成相同的代码

更新

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

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

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM