【发布时间】:2015-02-06 13:31:24
【问题描述】:
如果符合 32 位(使用适用的寄存器重命名),下面的代码可以正常工作。但它在执行时会引发错误(并且“警告:对象文件“project1.o”包含 32 位绝对重定位到符号“.data.n_tc_p$project1_orbitkeyheader64$int64$longint$$int64_shufidx”。 " 编译时)。
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;
我该如何纠正这个问题(最好是对齐常量)。
编辑 我也尝试过使用 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;
这也有效,但没有明显的速度优势:
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;
【问题讨论】:
-
既然是局部变量,难道你不应该像
[rbp-8]那样处理局部变量吗? -
64 位模式不喜欢这个常量。 32位就可以了。这是一个定义对齐问题。我不需要像 rbp-8 这样的东西,因为我可以直接引用常量。
-
什么平台?我记得当符号实际上没有在任何地方定义时,我在 Windows 上看到过类似的错误。
-
我正在使用针对 Win64 / Athlon64 的 Lazarus / Free Pascal 进行编译。 Lazarus 在 32 位 VM 中,我从 C# 调用代码。在 32 位模式下,我可以在本地对其进行测试,并且可以正常工作(也没有编译器警告)。
标签: assembly lazarus freepascal