x64 代码中的对齐问题,Free Pascal

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)

Jes*_*ter 5

这可能根本不是对齐问题。编译器已向您发出警告,您的绝对引用SHUFIDX将被截断为 32 位。如果地址不在前 4GiB 内,则会导致错误的内存引用。您应该在调试器中检查这一点。

作为解决方法,您应该使用 rip-relative 或间接寻址。前者可能看起来像movdqu xmm1, [rip+SHUFIDX]movdqu xmm1, rel SHUFIDX类似的东西。请参阅编译器手册。

  • @IanC 为了其他人的利益,您能告诉我们编译器接受哪种语法吗? (2认同)