我試圖找到一個指令,將取代MOVZX
,因爲我使用EMU8086(模擬8086不支持MOVZX
)。是否有另一條類似於MOVZX的指令,但支持8086?
我發現的最接近的指令是CBW
,它將值存入寄存器AX
,但它僅用於有符號值。我需要一些適用於無符號值的東西。
我有什麼選擇?是否可以通過一條指令來完成?
我試圖找到一個指令,將取代MOVZX
,因爲我使用EMU8086(模擬8086不支持MOVZX
)。是否有另一條類似於MOVZX的指令,但支持8086?
我發現的最接近的指令是CBW
,它將值存入寄存器AX
,但它僅用於有符號值。我需要一些適用於無符號值的東西。
我有什麼選擇?是否可以通過一條指令來完成?
movzx
指令零延伸一個寬度較小的值適合寬度較大的寄存器。例如,movzx
將用於將16位值移入32位寄存器。 (這是對比movsx
,它不只是與符號擴展同樣的事情。你會使用movzx
當值是無符號的,並且movsx
當值簽名。)
正如你所指出的,這些指令直到386才推出,所以如果你的目標是前一代處理器,那麼你需要找到一個替代方案。
的基本策略是,正如其他人在評論中指出,要零目標先登記,然後在移動的較小值。這將完成與movzx
完全相同的事情。清零寄存器的明顯方法是使用mov reg, 0
,但使用xor reg, reg
來使用it is smaller and faster。因此,這樣的代碼:
movzx edx, WORD PTR [bx]
可以被替換爲:
xor edx, edx
mov dx, WORD PTR [bx]
在現代的處理器,這比movzx
慢,但它實際上是在386和486,其中movzx
相對較快慢。當然,在movzx
不存在的處理器上,您別無選擇。您可以通過提前發佈xor
指令來進一步降低成本,並將其穿插到其他代碼中。
這種方法的一個顯着缺點是你不能對存儲在寄存器中的值進行就地零擴展。也就是說,沒有辦法,當你有這樣的代碼使用這一招:
movzx edx, dx
相反,你將不得不使用一個臨時寄存器:
xor eax, eax
mov ax, dx
mov dx, ax ; optional, if you really needed the result to be in DX
或者,如果你是零 - 擴展8位值時,可以利用這樣一個事實,即可以在x86上獨立訪問16位寄存器的高8位和低8位,並且只需將高8位置零即可。例如:
mov al, BYTE PTR [bx]
xor ah, ah
; now read from value in AX
請注意,這適用於就地零擴展 - 只需將高8位置零。但是,這種技術不能用於零擴展16位值,因爲無法訪問32位寄存器的高16位。
幸運的是,需要對這些舊架構零擴展遠小於它在現代建築,因爲你不必對局部寄存器攤位和假相關的大力防範。
在評論中,有人擔心,所有的替代movzx
的需要多於一個指令。當然,這是真的。如果有一種方法可以在一條指令中完成,那麼386就不需要引入movzx
。如果您擔心執行速度,請考慮以上所述的xor
+ mov
將等於與movzx
一樣快(如果不是更快的話)。
如果你擔心的指令數,然後放心少代碼並不一定意味着更快代碼。事實上,在許多情況下,添加額外的指令可以使您的程序更快地執行。如果您正在嘗試優化特定的代碼塊,我鼓勵您在此處或Code Review(我們需要更多的彙編語言問題!)提出一個問題。
通過清除目標寄存器的前8位,可以從2條指令合成它。如'mov al,[foo]; mov ah,0'可以代替'movzx ax,[foo]'(當然有各種方法可以清除前8位)。 – Jester
在將子寄存器加載到有效地址的內容之前,清零目標寄存器。 – IInspectable
是的,但事情是,我需要在1個命令行執行它 – TotalyNotUbisoft