在 8086 微处理器上将 32 位两个数相乘

Jus*_*ork 2 assembly multiplication x86-16

我有代码示例,用于在 8086 上将两个 16 位数字相乘并尝试将其更新为两个 32 位数字相乘。

start:
 MOV AX,0002h ; 16 bit multiplicand
 MOV BX,0008h ; 16 bit multiplier
 MOV DX,0000h ; high 16 bits of multiplication
 MOV CX,0000h ; low 16 bits of multiplication
 MOV SI,10h ; loop for 16 times

LOOP:
 MOV DI,AX
 AND DI,01h
 XOR DI,01h
 JZ ADD
CONT:
 RCR DX,1
 RCR CX,1
 SHR AX,1
 DEC SI
 CMP SI,0
 JNZ LOOP
 JMP END ; ignore here, it's not about multiplication. 
ADD:
 ADD DX,BX
 JMP CONT
Run Code Online (Sandbox Code Playgroud)

上面的代码语句将两个 16 位数字相乘。

要更新 32 位两个数字,我知道我需要更新,例如:

  1. 更改AX00000002hBX00000008h
  2. 使用另外两个寄存器(我不知道我应该使用哪个寄存器)来保存第二和第三个 16 位乘法(因为乘法将是 64 位。4 次 16 位。我目前有 DX 和 CX。)
  3. 将循环编号更新为20hSI在那种情况下)(对于 32 位编号,这是 32 次)

8086 是 16 位微处理器,所以它的寄存器也是。我无法为寄存器分配 32 位长的数字。

8086的寄存器:

REG: AX, BX, CX, DX, AH, AL, BL, BH, CH, CL, DH, DL, DI, SI, BP, SP.
SREG: DS, ES, SS, and only as second operand: CS.
Run Code Online (Sandbox Code Playgroud)

资料来源:http : //www.electronics.dit.ie/staff/tscarff/8086_instruction_set/8086_instruction_set.html

我的问题是:

  1. 如何为一个 32 位数字处理两个不同的寄存器。(寄存器是 16 位的,所以我必须把数字分成两个寄存器)
  2. 我可以为此使用哪些寄存器?我可以随意使用任何寄存器吗?

提前致谢。

Ale*_*hak 5

给一个人一条鱼,等等等等……

很好,你有一个代码示例。但是你懂算法吗?

好了,让我们通过它一步一步上的简化的示例:在相乘两个8位寄存器ALAH,并且将结果存储在DX

顺便说一句,你可以使用任何你喜欢的寄存器,除非这个或那个指令需要任何特定的寄存器。例如,SHL reg, CL.

但在我们真正开始之前,对您提供的算法进行了一些优化。你知道,组装就是优化。无论是速度还是尺寸。否则你会在 C# 或 smth 中做膨胀软件。别的。

MOV DI,AX
AND DI,01h
XOR DI,01h
JZ ADD
Run Code Online (Sandbox Code Playgroud)

这部分所做的只是检查是否设置了第一个位(位#0)AX。你可以简单地做

TEST AX, 1
JNZ ADD
Run Code Online (Sandbox Code Playgroud)

但是您只需要测试一位,TEST AL, 1而不是为TEST AX, 1您节省一个字节。

下一个,

RCR DX,1
Run Code Online (Sandbox Code Playgroud)

不需要轮换,所以它可以简单地是SHR DX, 1. 但是这两条指令的执行时间相同,并且都是两个字节长,因此在本例中无关紧要。

下一个,

DEC SI
CMP SI,0
JNZ LOOP
Run Code Online (Sandbox Code Playgroud)

在 之后永远不要与零进行比较DEC。是动静!简单地做

DEC SI
JNZ LOOP
Run Code Online (Sandbox Code Playgroud)

接下来,不必要的循环拆分

JZ ADD
CONT:
. . .
JMP END
ADD:
ADD DX, BX
JMP CONT
END:
. . .
Run Code Online (Sandbox Code Playgroud)

应该

JNZ CONT
ADD DX, BX
CONT:
. . .
END:
. . .
Run Code Online (Sandbox Code Playgroud)

在这里,我们使用了一些优化的例程:

LOOP:
 TEST AL, 1
 JZ SHORT CONT
 ADD DX, BX
CONT:
 RCR DX, 1
 RCR CX, 1
 SHR AX, 1
 DEC SI
 JNZ LOOP
END:
Run Code Online (Sandbox Code Playgroud)

就是这样。现在回到(或向前?)这段代码实际上做了什么。以下代码示例完全模仿您的示例,但适用于 8 位寄存器。

 MOV AL,12h   ; 8 bit multiplicand
 MOV AH,34h   ; 8 bit multiplier
 XOR DX, DX   ; result
 MOV CX, 8    ; loop for 8 times

LOOP:
 TEST AL, 1
 JZ SHORT CONT
 ADD DH, AH
CONT:
 SHR DX, 1
 SHR AL, 1
 DEC CX
 JNZ LOOP
END:
Run Code Online (Sandbox Code Playgroud)

这是一个长乘法算法

 12h = 00010010
               x
 34h = 01110100
       --------
       00000000
      01110100
     00000000
    00000000
   01110100
  00000000
 00000000
00000000
Run Code Online (Sandbox Code Playgroud)

将 shift 34h 添加两次:

0000000011101000
+
0000011101000000
----------------
0000011110101000 = 03A8
Run Code Online (Sandbox Code Playgroud)

就是这样!现在要使用更多数字,您可以使用相同的方法。下面是 fasm 语法的实现。结果存储在DX:CX:BX:AX

Num1    dd 0x12345678
Num2    dd 0x9abcdef0

 mov si, word [Num1]
 mov di, word [Num1 + 2]
 xor ax, ax
 xor bx, bx
 xor cx, cx
 xor dx, dx
 mov bp, 32

_loop:
 test si, 1
 jz short _cont
 add cx, word [Num2]
 adc dx, word [Num2 + 2]
_cont:
 rcr dx, 1
 rcr cx, 1
 rcr bx, 1
 rcr ax, 1
 rcr di, 1
 rcr si, 1
 dec bp
 jnz short _loop
Run Code Online (Sandbox Code Playgroud)

干杯;)