Iam*_*mIC 3 assembly freepascal lazarus
如果针对 32 位进行编译(使用适用的寄存器重命名),下面的代码可以正常工作。但它在执行时会抛出错误(并且“警告:目标文件“project1.o”包含到符号“.data.n_tc_p$project1_orbitkeyheader64$int64$longint$$int64_shufidx”的32位绝对重定位。”编译时)。
function SwapBytes64(const Val: Int64): Int64;
{$A 16}
const
SHUFIDX : array [0..1] of Int64 = ($0001020304050607, 0);
begin
asm
movq xmm0, rcx
pshufb xmm0, SHUFIDX // throws
movq rax, xmm0
end;
end;
Run Code Online (Sandbox Code Playgroud)
我该如何纠正这个问题(最好是对齐常数)。
编辑 我也尝试使用 movdqu。
答案 这是@Jester 答案的结果:
function SwapBytes64(const Val: Int64): Int64;
const
SHUFIDX : array [0..1] of Int64 = ($0001020304050607, 0);
begin
asm
movq xmm0, rcx
movdqu xmm1, [rip+SHUFIDX]
pshufb xmm0, xmm1
movq rax, xmm0
end;
end;
Run Code Online (Sandbox Code Playgroud)
这也有效,但没有明显的速度优势:
function SwapBytes64(const Val: Int64): Int64;
const
SHUFIDX : array [0..1] of Int64 = ($0001020304050607, 0);
begin
asm
movq xmm0, rcx
pshufb xmm0, [rip+SHUFIDX]
movq rax, xmm0
end;
end;
Run Code Online (Sandbox Code Playgroud)
这可能根本不是对齐问题。编译器已向您发出警告,您的绝对引用SHUFIDX将被截断为 32 位。如果地址不在前 4GiB 内,则会导致错误的内存引用。您应该在调试器中检查这一点。
作为解决方法,您应该使用 rip-relative 或间接寻址。前者可能看起来像movdqu xmm1, [rip+SHUFIDX]或movdqu xmm1, rel SHUFIDX类似的东西。请参阅编译器手册。