簡體   English   中英

x64代碼中的對齊問題,Free Pascal

[英]Alignment issue in x64 code, Free Pascal

如果符合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;

它可能根本不是對齊問題。 編譯器已警告您對SHUFIDX的絕對引用將被截斷為32位。 如果地址不在第一個4GiB內,則會導致錯誤的內存引用。 您應該在調試器中檢查它。

作為解決方法,您應該使用rip-relative或indirect尋址。 前者可能看起來像movdqu xmm1, [rip+SHUFIDX]movdqu xmm1, rel SHUFIDX或類似的東西。 請參閱編譯器手冊。

與您的實際問題無關:您的代碼不安全。 除非你編寫一個純匯編函數(“匯編程序; asm ... end;”或-in Delphi模式 - 只包含一個“asm ... end;”塊而沒有周圍的“begin .. end;”,編譯器可以插入匯編程序塊之前和之后的代碼。特別是,在匯編程序塊執行完畢后,它可能會覆蓋rax的值。

要解決此問題,要么使您的函數成為純匯編函數,要么在末尾添加“movq @result,rax”。

RIP + Var名稱解決了我的問題,其中有問題的變量被截斷為32位內存分配。 我甚至將變量的空間表示為Int64而沒有成功。 使用值加載RAX,然后將其分配給變量工作,但需要額外的編碼使32位代碼塊大小加倍。

MOV qword[var], RBX會拋出錯誤

這可以工作,但膨脹代碼:

MOV RAX, RBX
MOV qword[var], RAX

...雖然這可以按照預期的方式使用更少的MOV指令:

MOV qword[RIP + var], RBX

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM