C
代码只是否定double的值,但汇编指令涉及逐位XOR
和指令指针。有人可以解释发生了什么,为什么它是一个最佳解决方案。谢谢。
test.c 的内容:
void function(double *a, double *b) {
*a = -(*b); // This line.
}
生成的汇编程序指令:
(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
处的汇编程序指令表示&#34;此行&#34;但是我无法理解它是如何工作的。 xorpd/xorps
指令应该是按位XOR
,PTR [rip]
是指令指针。
我怀疑在执行时rip
指向0f 57 05 00 00 00 0f
字节附近的某个位置,但我无法弄清楚,这是如何工作的以及两个编译器的原因选择这种方法。
P.S。我应该指出,这是使用-O3
答案 0 :(得分:7)
对我而言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
此处xorpd
指令使用指令指针相对寻址,偏移量指向带有64位值.LC0
的{{1}}标签(第63位设置为1)。
0x8000000000000000
如果你的编译器是big endian这些swaped的行。
使用.LC0:
.long 0
.long -2147483648
对double值进行xoring,将符号位(第63位)设置为负值。
clang使用0x8000000000000000
指令的方式与x值为double值的前32位相同。
如果使用xorps
选项运行对象转储,它将显示在运行之前应该对程序执行的重定位。
-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
我们的重定位类型为R_X86_64_PC32。
PS:我正在使用gcc 6.3.0
答案 1 :(得分:4)
xorps xmm0,XMMWORD PTR [rip+0x0]
[]
包围的指令的任何部分都是对内存的间接引用。
在这种情况下,引用地址RIP+0
的内存
(我怀疑它实际上是RIP+0
,你可能已经编辑了实际的偏移量)
X64指令集添加instruction pointer relative addressing。这意味着您可以在程序中拥有(通常只读)数据,即使程序在内存中移动也可以轻松解决。
XOR xmm0,Y
反转xmm0中Y
中设置的所有位
否定涉及反转符号位,因此这就是使用xor的原因。特别是xorpd/s
,因为我们正在处理双重呼吁。单花车。