GCC和Clang編譯器似乎使用了一些黑暗魔法。 C
代碼只是否定了雙精度值,但彙編器指令涉及位方式XOR
和指令指針。有人可以解釋發生了什麼,爲什麼它是最佳解決方案。謝謝。古怪的SSE彙編指令雙重否定
void function(double *a, double *b) {
*a = -(*b); // This line.
}
將所得的彙編程序指令:
test.c的內容
(gcc)
0000000000000000 <function>:
0: f2 0f 10 06 movsd xmm0,QWORD PTR [rsi]
4: 66 0f 57 05 00 00 00 xorpd xmm0,XMMWORD PTR [rip+0x0] # c <function+0xc>
b: 00
c: f2 0f 11 07 movsd QWORD PTR [rdi],xmm0
10: c3 ret
(clang)
0000000000000000 <function>:
0: f2 0f 10 06 movsd xmm0,QWORD PTR [rsi]
4: 0f 57 05 00 00 00 00 xorps xmm0,XMMWORD PTR [rip+0x0] # b <function+0xb>
b: 0f 13 07 movlps QWORD PTR [rdi],xmm0
e: c3 ret
在地址0x4
彙編指令表示 「這條線」,然而我無法理解它是如何工作的。 xorpd/xorps
指令應該是位明智的XOR
和PTR [rip]
是指令指針。
我懷疑在執行的那一刻rip
指向接近0f 57 05 00 00 00 0f
字節的地方,但我無法弄清楚,這是如何工作的,爲什麼兩個編譯器都選擇這種方法。
P.S.我應該指出,這是通過使用-O3
我無法重現這一點。兩個編譯器都使用一個表示-0.0的常量進行異或操作,它們從內存中加載。這對[RIP相對抵銷]有意義(https://stackoverflow.com/questions/44967075/why-does-this-movss-instruction-use-rip-relative-addressing/44967386#44967386)。沒有意義的是,你的反彙編顯示它們將下一條指令的字節加載爲浮點常量。這是不對的。你有可能以某種方式剝離了反彙編的偏移量嗎?或者你的反彙編人員感到困惑? –
我絕對不會手動更改任何東西。使用上面的代碼逐字和命令'gcc test.c -c -O3 -o test.o'和'objdump -S -M intel test.o'這是我得到的輸出。我會重申一下,我知道'PTR [rip]'是什麼,並且可以通過改變雙精度中的前導位來反轉符號。我所問的原因是因爲這兩個想法並沒有混合在我的腦海中。 – RuRo
你越確定自己沒有犯錯,你做得越有可能。從控制檯複製錯誤的部分。抱歉,彙編程序列表現在應該是正確的。奇怪的'xor'與'rip'仍然存在。 – RuRo