我制作一些只与字符比较的汇编测试代码, 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'?
答案 0 :(得分:2)
可以看出第一次比较是针对[x41 ... x59]范围的。第二次比较是针对[x40 ... x5a]范围。基本上,编译器进入
if ( 'A'-1 < test && test < 'Z'+1 )
然后生成相同的代码
更新
为了弄清楚为什么我认为编译器更喜欢JL和JLE。 JLE依赖于更新的标志值(ZF = 1),但JL不会。因此,即使指令时序本身相同,JLE也会引入可能会损害指令级并行性的依赖性
因此,明确选择 - 转换代码以使用更简单的指令。
答案 1 :(得分:1)
通常,您不能强制编译器发出特定指令。在这种情况下,如果您删除常量,则可能会成功,因此编译器无法对其进行调整。请注意,由于表达式的性质,编译器可能仍会反转其中一个测试,从而引入等于。您可以使用goto
来解决这个问题。显然,这两种变化都会产生更糟糕的代码。