我正在玩asmjit并生成程式集。因此,我注意到不能將 64 位常量用于指令(不包括mov有意義的)。
因此,我將 64 位常量壓入堆疊并通過訪問堆疊而不是將常量用作運算元來使用它們。不同的資源說,可以將記憶體用作and指令的運算元(例如[1],[2])。
但是,我注意到該and指令沒有按預期作業。我將從我的代碼中舉一個例子:
mov r14, qword ptr [r15 32] ; r14 holds a masked pointer now
mov qword ptr [rsp], 281474976710655 ; 0xFFFFFFFFFFFF is the mask for the pointer
and r14, [rsp] ; Using pointer&mask I want to unmask the pointer
在該and指令之后, in 的值r14保持不變:
r14之前and:421609184805440r14之后and:421609184805440
改用暫存器時,一切都按預期作業:
mov r14, qword ptr [r15 32] ; r14 holds a masked pointer now
mov r13, 281474976710655 ; 0xFFFFFFFFFFFF is the mask for the pointer
and r14, r13 ; Using pointer&mask I want to unmask the pointer
r14之前and:421723605418560r14之后and:140248628707904
當然,我可以使用暫存器而不是訪問堆疊,但我會對為什么它的行為不同感興趣。
uj5u.com熱心網友回復:
看起來你沒有檢查 asmjit 錯誤。 檔案說有一個
kErrorInvalidImmediate- Invalid immediate(X86 越界,ARM 上的模式無效)。
唯一可以使用 64 位立即數的 x86-64 指令是mov-immediate to register,這是一種特殊的 no-modrm 操作碼,它為我們提供 5-bytemov eax, 12345或 10-byte mov rax, 0x0123456789abcdef,其中 REX.W 前綴會更改要查找的操作碼一個 64 位立即數。請參閱https://www.felixcloutier.com/x86/mov /為什么我們不能將 64 位立即值移動到記憶體中?
你的標題是紅鯡魚。m64這與有一個運算元無關and,這是問題所在。您可以通過使用除錯器單步執行 asm 并檢查 之前的兩個運算元and(包括記憶體中的運算元)來驗證這一點。(它可能-1來自0xFFFFFFFFfor 的立即數mov m64, sign_extended_imm32,這將解釋 AND 不更改 R14 中的值)。
JITed 機器代碼的反匯編也應該向您顯示實際編碼的立即數;再次,除錯器可以在您單步執行時提供。
將臨時暫存器用于常量(如mov r14, 0xFFFFFFFFFFFF),然后and reg,mem進行加載和屏蔽。
或者更好的是,如果您使用 JITint 的目標機器具有BMI1andn,則在回圈外構造反轉常量一次,mov r13, ~0xFFFFFFFFFFFF然后在回圈內使用andn r14, r13, [r15 32]執行加載 并且不破壞掩碼,所有這些指令都可以解碼為單個指令uop 在 Intel/AMD CPU 上。
如果你不能在回圈中重用一個常量暫存器,也許mov reg,imm64, then push regormov mem,reg并在未來的 AND 指令中使用它。或者在足夠接近 RIP 相對尋址模式的某個地方發出一些常量資料,盡管這在每條and指令上都需要更多的代碼大小。(ModRM 4 位元組 rel32,與 ModRM SIB 0 或 1 位元組用于堆疊上接近 RSP 的資料)。
順便說一句,如果您只是截斷而不是符號擴展,那么您還假設這是地址位于虛擬地址空間(即用戶空間)的下半部分。不過沒關系。有趣的事實:未來的 x86 CPU(第一個 Sapphire Rapids)將具有一個可選功能,作業系統可以啟用該功能以透明地忽略高位,MSB 除外:LAM = 線性地址掩碼。請參閱英特爾的未來擴展手冊。
因此,如果此功能啟用了用戶空間的 48 位掩碼,您可以完全跳過 AND 掩碼。(如果您的代碼確保位 47 與位 63 匹配;您可能希望保持最高位未修改或為 0,以便您的代碼可以在可用于保存指令時利用 LAM)。
如果您要屏蔽以保持低 32,則可以mov r14d, [r15 32]將值的低 dword 零擴展為 64 位 R14。但是為了保持高 48 位或 57 位,您需要在暫存器中使用掩碼或bzhiBMI2 48。
轉載請註明出處,本文鏈接:https://www.uj5u.com/net/412645.html
標籤:
