我如何在汇编中将两个 32 位数字相乘或一个 32 位另一个 16 位相乘,有人知道算法吗?
data1 dw 32bit
data2 dw 32bit
mov ax,data2
Mul data1
我如何在汇编中将两个 32 位数字相乘或一个 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
第二步( ) 之后我们不需要,因为它的高半部分最多为。 那时已经为零(因为此代码仅工作一次),因此无法包装并产生进位。它最多可以产生.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