以下代码是由g ++ 5.4.0编译的x64。左边是编译输出。右边的东西就是我所期望的样子。当然,右边的stuf可能在语法上不正确。这段代码应该基本上做:
if(i%3 == 0) do_stuff
400512将把你带到if块后面的空格
mov -0x4(%rbp),%ecx mov -0x4(%rbp), %eax
mov $0x55555556,%edx idvq $0x3
mov %ecx,%eax cmp %edx, 0x0
imul %edx jnz 400512 <main+0x3c>
mov %ecx,%eax
sar $0x1f,%eax
sub %eax,%edx
mov %edx,%eax
mov %eax,%edx
add %edx,%edx
add %eax,%edx
mov %ecx,%eax
sub %edx,%eax
test %eax,%eax
jne 400512 <main+0x3c>
我的问题是那些比我更聪明的人:为什么g ++有更多来计算模数,有人可以向我解释它在做什么。
答案 0 :(得分:0)
出于我的好奇心,Ross Ridge对unsigned int
修改的评论产生了更短的代码:
bar(unsigned int):
mov eax, edi
mov edx, -1431655765
mul edx
shr edx
lea eax, [rdx+rdx*2]
cmp edi, eax
je .L4
rep ret
.L4:
jmp foo()
但是回到int
版本......对于编译器来说它很整洁......但它仍然感觉有些......
等等,它是否正确划分为3然后再将其相乘,然后检查是否计算了相等的数字?嗯......但是我们只想要mod 3 == 0
测试,对吧?
那么这也应该这样做:
bar(int):
mov eax, edi
mov edx, 1431655766
imul edx
; don't +1 of div result for negative edi
; mov eax, edi
; sar eax, 31
; sub edx, eax
; instead do +3 for all results
lea eax, [rdx+rdx*2+3]
sub eax, edi ; eax = 0, 1, 2 or 3 (!)
jpe .L4 ; so parity-even condition will resolve it (!)
rep ret
.L4:
jmp foo()
不幸的是,这是特殊情况&#34; mod 3&#34;仅限优化(而且我不确定这真的是否会改善任何东西)...... :)但我无法抗拒&#34;高尔夫&#34;它有点。