MOVZX
EMU8086 (をサポートしない 8086 をエミュレートする) を使用しているため、を置き換える命令を見つけようとしていMOVZX
ます。
私が見つけた最も近い命令はCBW
、レジスタに値を入れる でしたが、これはAX
符号付きの値のみを対象としています。符号なしの値で機能するものが必要です。
私のオプションは何ですか?単一の命令でそれを行うことは可能ですか?
このmovzx
命令は、幅の広いレジスタに収まるように幅の狭い値をゼロ拡張します。たとえばmovzx
、16 ビット値を 32 ビット レジスタに移動するために使用されます。(符号拡張movsx
を除いて同じことを行う とは対照的です。値が符号なしの場合と、値が符号付きの場合に使用します。)movzx
movsx
ご指摘のとおり、これらの命令は 386 まで導入されなかったため、以前の世代のプロセッサをターゲットにしている場合は、代替手段を見つける必要があります。
他の人がコメントで指摘したように、基本的な戦略は、最初に宛先レジスタをゼロにしてから、より小さい値を に移動することです。これは、 とまったく同じことを達成しmovzx
ます。レジスタをゼロにする明白な方法は を使用することですが、 を使用したmov reg, 0
方が小さくて高速xor reg, reg
です。したがって、次のようなコード:
movzx edx, WORD PTR [bx]
次のように置き換えることができます:
xor edx, edx
mov dx, WORD PTR [bx]
最新のプロセッサでは、これは よりも遅くなりますがmovzx
、実際にmovzx
は が比較的遅い 386 および 486 でより高速になります。もちろん、存在しないプロセッサでmovzx
は、選択の余地はありません。xor
命令を先に発行し、他のコードに分散させることで、コストをさらに最小限に抑えることができます。
このアプローチの重大な欠点の 1 つは、レジスタに格納されている値に対してインプレース ゼロ拡張を実行できないことです。つまり、次のようなコードがある場合、このトリックを使用する方法はありません。
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
コメントでは、すべての選択肢が複数の指示
を必要とするという懸念が提起されました。もちろん、それは本当です。1 つの命令でそれを行う方法があれば、386 が導入する必要はなかったでしょうmovzx
。実行速度が心配な場合は、xor
+が利用可能である場合と
mov
同じくらい高速ではないにしても、上記で述べたことを考慮してください。movzx
命令数が気になる場合は、コードが少ないからといってコードが高速になるとは限らないのでご安心ください。実際、多くの場合、命令を追加すると、プログラムの実行速度が向上します。コードの特定のチャンクを最適化しようとしている場合は、ここまたはコード レビューで質問することをお勧めします(アセンブリ言語に関する質問がもっと必要です!)。