アセンブリで 2 つの 32 ビット桁を乗算する方法、または 1 つの 32 ビットと別の 16 ビットを乗算するにはどうすればよいですか?アルゴリズムは誰でも知っていますか?
data1 dw 32bit
data2 dw 32bit
mov ax,data2
Mul data1
アセンブリで 2 つの 32 ビット桁を乗算する方法、または 1 つの 32 ビットと別の 16 ビットを乗算するにはどうすればよいですか?アルゴリズムは誰でも知っていますか?
data1 dw 32bit
data2 dw 32bit
mov ax,data2
Mul data1
まず、dw
16 ビット (「ワード」) 値を作成するために使用されます。32 ビット値は保持されません。dd
32 ビットの「dword」を格納するために使用するか、16 ビット値のペアを使用する必要があります。
32 ビット値のペアを乗算する場合、結果は 64 ビットになります (例: 0xFFFFFFFF * 0xFFFFFFFF = 0xFFFFFFFE00000001)。8086 (および 80386 以降のリアル モード コードだけでなく) には、MUL 命令がありますが、2 つの 16 ビット値の乗算 (および 32 ビットの結果の取得) に制限されています。これは、各 32 ビット値を 16 ビット値のペアとして扱いたいということです。
A が A_low (最初の 32 ビット数の最下位 16 ビット) と A_high (最初の 32 ビット数の最上位 16 ビット) に分割され、B が同じように B_low と B_high に分割された場合。それから:
A * B = A_low * B_low
+ ( A_high * B_low ) << 16
+ ( A_low * B_high ) << 16
+ ( A_high * B_high ) << 32
コードは次のようになります (NASM 構文)。
section .data
first: dw 0x5678, 0x1234 ;0x12345678
second: dw 0xDEF0, 0x9ABC ;0x9ABCDEF0
result: dw 0, 0, 0, 0 ;0x0000000000000000
section .text
mov ax,[first] ;ax = A_low
mul word [second] ;dx:ax = A_low * B_low
mov [result],ax
mov [result+2],dx ;Result = A_low * B_low
mov ax,[first+2] ;ax = A_high
mul word [second] ;dx:ax = A_high * B_low
add [result+2],ax
adc [result+4],dx ;Result = A_low * B_low
; + (A_high * B_low) << 16
mov ax,[first] ;ax = A_low
mul word [second+2] ;dx:ax = A_low * B_high
add [result+2],ax
adc [result+4],dx ;Result = A_low * B_low
; + (A_high * B_low) << 16
; + (A_low * B_high) << 16
adc word [result+6], 0 ; carry could propagate into the top chunk
mov ax,[first+2] ;ax = A_high
mul word [second+2] ;dx:ax = A_high * B_high
add [result+4],ax
adc [result+6],dx ;Result = A_low * B_low
; + (A_high * B_low) << 16
; + (A_low * B_high) << 16
; + (A_high * B_high) << 32
2 番目のステップ ( )の後は必要ありません。 はその時点ですでにゼロであるため (このコードは 1 回しか機能しないため)、ラップしてキャリーアウトを生成することはできません。せいぜい.adc word [result+6], 0
[first+2] * [second]
0xfffe
[result+4]
adc [result+4],dx
0xffff
(すでにゼロ化されている部分に依存することを避けるためにadc dx, 0
/として実行できます。同様に、ゼロ化されたレジスタへの最初の書き込みに使用して、最初のゼロ化なしでこのコードを使用できるようにすることができます。)mov [result+4], dx
result
adc
[result+6]
result
実際に 80386 以降を使用している場合は、はるかに簡単です。
section .data
first: dd 0x12345678
second: dd 0x9ABCDEF0
result: dd 0, 0 ;0x0000000000000000
section .text
mov eax,[first] ;eax = A
mul dword [second] ;edx:eax = A * B
mov [result],eax
mov [result+4],edx ;Result = A_low * B_low