10

ポール・カーターによるPCアセンブリから80386を学んでいます

  mul source
  • オペランドがバイト サイズの場合、AL レジスタのバイトで乗算され、結果が AX の 16 ビットに格納されます。

大丈夫。

  • ソースが 16 ビットの場合、AX のワードで乗算され、32 ビットの結果が DX:AX に格納されます。

Q1:なぜ DX:AX なのですか? EAX / EDXに保存できないのはなぜですか?

imul本当に紛らわしい

imul dest, source1
imul dest, source1, source2

代替テキスト

表の理解に問題があります。

Q2:表の 2 番目のエントリ。繰り返しますが、なぜ DX:AX なのか。なぜ EAX や EDX ではないのでしょうか?

次のコード スニペットを検討してください。

imul eax ; edx:eax = eax * eax
mov ebx, eax ; save answer in ebx
mov eax, square_msg ; square_msg db "Square of input is ", 0
call print_string ; prints the string eax
mov eax, ebx 
call print_int ;  prints the int stored in eax
call print_nl ; prints new line

Q3:前に言ってたけどThe notation EDX:EAX means to think of the EDX and EAX registers as one 64 bit register with the upper 32 bits in EDX and the lower bits in EAX.、答えもedxに保存されてるんだよね?上記のコードでは、EDX を考慮していません。単に EAX を参照しているだけです。これはまだどのように機能していますか?

Q4:テーブルの残りのすべてのエントリに問題があります。2 つの n ビット数 (n = 8/16/32 ビット) の最悪の場合の乗算結果は 2n ビットです。2 つの 16/32 ビット乗算の結果を格納すると、レジスタ自体が同じサイズになるのはなぜですか?

4

5 に答える 5

7

imul 命令にはさまざまなバリエーションがあります。

あなたが見つけたバリアントは、16 ビットの乗算です。imul への引数として渡されたものと AX レジスタを乗算し、結果を DX:AX に格納します。

1 つの 32 ビット バリアントは 16 ビット乗算のように機能しますが、レジスタを EDX:EAX に書き込みます。このバリアントを使用するには、32 ビット ソース オペランドを使用するだけです。

例えば:

  ; a 16 bit multiplication:
  mov ax, [factor1]
  mov bx, [factor2]
  imul bx              ; 32-bit result in DX:AX
  ; or  imul  word [factor2]

  ; a 32 bit multiplication:
  mov eax, [factor1]
  mov ebx, [factor2] 
  imul ebx             ; 64-bit result in EDX:EAX

386 以降でimulは、2 オペランド形式で an を記述することもできます。これにより、はるかに柔軟で作業しやすくなります。このバリアントでは、任意の 2 つのレジスタをソースと宛先として自由に選択でき、CPU は上位半分の結果をどこにでも書き込むために時間を無駄にしません。EDXを破壊しません。

  mov   ecx, [factor1]
  imul  ecx, [factor2]    ; result in ecx, no other registers affected
  imul  ecx, ecx          ; and square the result

または、符号付き 16 ビット入力をimul. (符号なし入力には movzx を使用)

  movsx   ecx, word [factor1]
  movsx   eax, word [factor2]  ; sign-extend inputs to 32-bit
  imul    eax, ecx             ; 32-bit multiply, result in EAX
  imul    eax, eax             ; and square the result

この imul のバリアントは386 で導入され、16 ビットおよび 32 ビットのオペランド サイズで使用できます。(および 64 ビット モードでは 64 ビットのオペランド サイズ)。

32 ビット コードでは、386 のような命令imul reg, reg/memが利用可能であると常に想定できますが、古い CPU を気にしない場合は、16 ビット コードで使用できます。

186 では、3 オペランドの即値形式が導入されました。

imul  cx, bx, 123        ; requires 186

imul  ecx, ebx, 123      ; requires 386
于 2009-12-22T18:03:13.413 に答える
7

Q1/Q2: x86 命令セットは、16 ビットの履歴を維持します。16 ビットの乗算を実行すると、答えは DX:AX に格納されます。16 ビットの土地ではそうだったからです。

Q3: コードは に格納された結果の上位 32 ビットを無視するため、2^16 より大きい数値の 2 乗を計算しようとすると、表示されたコードにはバグがありますedx

Q4: 表を読み間違えているのではないかと思います。8 ビットの乗算は 16 ビットの結果に格納されます。16 ビットの乗算は 32 ビットの結果に格納されます。32 ビットの乗算は 64 ビットの結果に格納されます。具体的にどの行を指していますか?

于 2009-12-22T17:56:38.247 に答える
6

Q1/Q2:なぜ DX:AX なのですか? EAX / EDXに保存できないのはなぜですか?

他の人が言ったように、それは後方互換性のためだけです。元の(i)mul命令は、32 ビット x86 命令セットが登場するずっと前に登場した 16 ビット x86 のものであり、E レジスタがなかったため、結果を eax/edx に格納できませんでした。

Q3:上記のコードでは、EDX を考慮していません。単に EAX を参照しているだけです。これはどのように機能していますか?

結果がオーバーフローしない小さな値を入力したため、違いがわかりませんでした。十分に大きな値 (>= 16 ビット) を使用すると、EDX != 0 が表示され、出力結果が正しくないことがわかります。

Q4: 2 つの 16/32 ビット乗算の結果を格納すると、レジスタ自体が同じサイズになるのはなぜですか?

結果がオペランドと同じサイズのままというわけではありません。2 つの n ビット値を乗算すると、常に 2n ビット値が生成されます。しかし、imul r16, r/m16[, imm8/16]およびそれらの 32/64 ビット版では、上位 n ビットの結果は破棄されます。これらは、結果の下位 16/32/64 ビットのみが必要な場合(つまり、非拡大乗算)、または結果がオーバーフローしないことを保証できる場合に使用されます。

  • 2 オペランド形式 — この形式では、デスティネーション オペランド (最初のオペランド) がソース オペランド (2 番目のオペランド) で乗算されます。デスティネーション オペランドは汎用レジスタで、ソース オペランドは即値、汎用レジスタ、またはメモリ ロケーションです。中間積 (入力オペランドのサイズの 2 倍) は切り捨てられ、宛先オペランドの場所に格納されます。
  • [... 3 オペランド形式でも同じ]

https://www.felixcloutier.com/x86/IMUL.html

imul現在の最新のコンパイラは、符号付き乗算と符号なし乗算の両方にマルチオペランドをほぼ排他的に使用します。

于 2013-11-05T07:06:01.540 に答える
1

Q1/Q2: その理由は歴史的なものだと思います。32 ビットがオプションになる前は、eax や edx はありませんでした。32 ビット機能は、逆互換性のために追加されました。

Q3: 下位ビットは eax になります。上位ビットへのオーバーフローがない限り、気にするのはこれらだけです。

Q4: 確かに変わったテーブルです。でもわかると思います。

于 2009-12-22T17:59:43.863 に答える
1

A1: mul元々は 8086/8088/80186/80286 プロセッサに存在し、E** (拡張、つまり 32 ビットの E) レジスタがありませんでした。

A2: A1 を参照してください。

アセンブリ言語プログラマーとしての私の仕事は、これらの 32 ビット Intel が一般的になる前に Motorola 680x0 ファミリーに移行したので、そこでやめます :-)

于 2009-12-22T18:00:43.080 に答える