web-dev-qa-db-ja.com

たとえば、「movb $ 1、%eax」ではなく、「movl $ 1、%eax」を使用するのはなぜですか。

タイトルにあるように、「movb $ 1、%eax」ではなく「movl $ 1、%eax」を使用するのはなぜですか。movlは%eaxの上位ビットをゼロにするように言われましたが、そうではありません。 %eaxは、システムのワードサイズのサイズに相当するレジスタですか?つまり、movlは実際には整数演算です(長くはありませんか?)

私は明らかにそれについて少し混乱しています。ありがとう。

たとえば、「movb $ 1、%eax」とは対照的です

この命令は無効です。 movb命令でeaxを使用することはできません。代わりに、8ビットレジスタを使用します。例えば:

movb $ 1、$ al

しかし、%eaxは、システムのワードサイズのサイズに相当するレジスタではありませんか?

いいえ。EAXは、システムのレジスタサイズに関係なく、常に32ビット値になります。

C変数サイズとレジスタサイズを混同しています。 C変数のサイズは、システムとコンパイラによって異なる場合があります。

アセンブリはCよりも単純です。GASアセンブリでは、命令の末尾に「b」、「s」、「w」、「l」、「q」、または「t」の文字を付けて、操作するオペランドのサイズを決定します。

* b = byte (8 bit)
* s = short (16 bit integer) or single (32-bit floating point)
* w = Word (16 bit)
* l = long (32 bit integer or 64-bit floating point)
* q = quad (64 bit)
* t = ten bytes (80-bit floating point)

これらのサイズは一定です。それらは決して変更されません。 alは常に8ビットで、eaxは常に32ビットです。

40
Jason

32ビットマシンでは、%eaxは4バイト(32ビット)のレジスタです。 movlは4バイトすべてに書き込みます。あなたの例では、上位3バイトをゼロにし、最下位バイトに1を入れます。 movbは下位バイトを変更するだけです。

7
Victor Shnayder

%eaxは32ビットレジスタです。より狭い幅を使用するには、16ビットの場合は%axが必要です。 %axは、%ahの上位バイトの場合は%axに、下位バイトの場合は%alにさらに分割できます。同じことが他のx86GPRにも当てはまります。

mov命令のIntel命令セットリファレンスを見ると、1バイトを32ビットレジスタに移動できるバリアントは見当たりません。おそらく%alへの移動として解釈されます。 。

movlは32ビット命令であるため、上位バイトの値はゼロに対応します即値の場合。メモリから移動する場合は、32ビットワード全体を移動することになります。

%eaxを選択しない限り、またはmovl $0, %eaxを実行しない限り、xorl %eax, %eaxはゼロになりません。それ以外の場合は、以前にそこにあった値を保持します。 movl $1, %eaxを実行すると、32ビット命令が32ビットの即値をレジスタに移動するため、レジスタに0x00000001が含まれることになります。

5
Aaron Klotz

longは元々32ビットでしたが、intshortは16ビットでした。また、誰かが新しいオペレーティングシステムを発表するたびに、オペコードの名前が変わることはありません。

3
Anon.

%eaxは、32ビットマシンでは32ビットです。 %axは16ビットであり、%ah%alはその8ビットの上位と下位の構成要素です。

したがって、ここではmovlが完全に有効です。効率的には、movlmovbと同じくらい高速であり、%eaxの上位3バイトをゼロにすることが望ましいプロパティであることがよくあります。後で32ビット値として使用したい場合があるため、movbはそこにバイトを移動するのに適した方法ではありません。

2
Eli Bendersky

2番目の選択ではエラーが発生するだけで、x86にはその命令がありません。 X86は、特定のレジスタへのバイトのロードに関して少しユニークです。はい、ほとんどの命令セットアーキテクチャでは、オペランドはゼロまたは符号拡張されていますが、x86では、一部の下位バイトまたは下位16ビットのみを書き込むことができます。

レジスターをクリアしてからインクリメントするなど、確かに他の選択肢もありますが、最初は合理的に見える3つの選択肢があります。

   0:   b8 01 00 00 00          movl   $0x1,%eax

   5:   31 c0                   xorl   %eax,%eax
   7:   b0 01                   movb   $0x1,%al

   9:   b0 01                   movb   $0x1,%al
   b:   0f b6 c0                movzbl %al,%eax

最初のバイトは5バイト、2番目のバイトは4バイト、3番目のバイトは5バイトです。したがって、スペースを最適化する場合は2番目が最適です。そうでない場合、高速で実行される可能性が最も高いのは最初のバイトだと思います。 X86は最近深くパイプライン化されているため、2つの命令が連動し、パイプラインハードウェアの詳細によっては、マシンにかなりの数の待機状態が必要になる場合があります。

もちろん、これらのx86 opsは、CPU固有の方法でCPU micro-opsに変換されています。何が起こるか。

2
DigitalRoss