RuR*_*uRo 0 assembly gcc sse x86-64 magic-numbers
GCC和Clang编译器似乎采用了一些黑暗魔法.该C代码只是否定了双重的价值,但汇编指令涉及逐位XOR和指令指针.有人可以解释发生了什么,为什么它是一个最佳解决方案.谢谢.
test.c的内容:
void function(double *a, double *b) {
*a = -(*b); // This line.
}
Run Code Online (Sandbox Code Playgroud)
生成的汇编程序指令:
(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
Run Code Online (Sandbox Code Playgroud)
(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
Run Code Online (Sandbox Code Playgroud)
地址处的汇编指令0x4代表"此行",但我无法理解它是如何工作的.该xorpd/xorps指令被认为是逐位XOR和PTR [rip]是指令指针.
我怀疑在执行的那一刻rip指向了接近0f 57 05 00 00 00 0f字节的区域,但我无法弄清楚,这是如何工作的以及为什么两个编译器都选择这种方法.
PS我应该指出这是使用编译的 -O3
对我来说,gcc使用-S -O3相同代码的选项的输出是:
.file "test.c"
.text
.p2align 4,,15
.globl function
.type function, @function
function:
.LFB0:
.cfi_startproc
movsd (%rsi), %xmm0
xorpd .LC0(%rip), %xmm0
movsd %xmm0, (%rdi)
ret
.cfi_endproc
.LFE0:
.size function, .-function
.section .rodata.cst16,"aM",@progbits,16
.align 16
.LC0:
.long 0
.long -2147483648
.long 0
.long 0
.ident "GCC: (Ubuntu 6.3.0-12ubuntu2) 6.3.0 20170406"
.section .note.GNU-stack,"",@progbits
Run Code Online (Sandbox Code Playgroud)
这里xorpd指令使用指令指针相对寻址,偏移量指向.LC0带有64位值的标签0x8000000000000000(第63位设置为1).
.LC0:
.long 0
.long -2147483648
Run Code Online (Sandbox Code Playgroud)
如果你的编译器是big endian这些swaped的行.
对double值进行xoring,0x8000000000000000将符号位(第63位)设置为负值.
clang使用xorps指令的方式与double值的前32位相同.
如果使用-r选项运行对象转储,它将显示在运行之前应该对程序执行的重定位.
objdump -d test.o -r
test.o: file format elf64-x86-64
Disassembly of section .text:
0000000000000000 <function>:
0: f2 0f 10 06 movsd (%rsi),%xmm0
4: 66 0f 57 05 00 00 00 xorpd 0x0(%rip),%xmm0 # c <function+0xc>
b: 00
8: R_X86_64_PC32 .LC0-0x4
c: f2 0f 11 07 movsd %xmm0,(%rdi)
10: c3 retq
Disassembly of section .text.startup:
0000000000000000 <main>:
0: 31 c0 xor %eax,%eax
2: c3 retq
Run Code Online (Sandbox Code Playgroud)
在这里,<function + 0xb>我们有一个R_X86_64_PC32类型的重定位.
PS:我正在使用gcc 6.3.0
| 归档时间: |
|
| 查看次数: |
174 次 |
| 最近记录: |