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

标签 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

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

要将其更新为 32 位两个数字,我知道我需要如下更新:

  1. AX 更改为 00000002h,将 BX 更改为 00000008h
  2. 再使用两个寄存器(我不知道应该使用哪个寄存器)来保存第二个和第三个16位乘法(因为乘法将是64位。16位乘法4次。我目前有DX和CX。)
  3. 将循环编号更新为 20h(在这种情况下为 SI)(对于 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.

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

我的问题是:

  1. 如何处理一个 32 位数字的两个不同寄存器。 (寄存器是16位的,所以我必须将数字分成两个寄存器)
  2. 我可以使用哪些寄存器来实现此目的?我可以随意使用any注册吗?

提前致谢。

最佳答案

授人以鱼,然后等等……

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

好吧,让我们通过一个简化的例子一步一步地看一下:将 ALAH 中的两个 8 位寄存器相乘,并将结果存储在 中DX.

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

但在我们真正开始之前,您提供的算法有一些优化。你知道, assembly 就是优化。无论是为了速度还是为了尺寸。否则你会用 C# 或其他方式编写臃肿软件。否则。

MOV DI,AX
AND DI,01h
XOR DI,01h
JZ ADD

这部分的作用只是检查AX中的第一位(位#0)是否已设置。 你可以简单地做

TEST AX, 1
JNZ ADD

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

下一步,

RCR DX,1

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

下一步,

DEC SI
CMP SI,0
JNZ LOOP

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

DEC SI
JNZ LOOP

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

JZ ADD
CONT:
. . .
JMP END
ADD:
ADD DX, BX
JMP CONT
END:
. . .

应该是

JNZ CONT
ADD DX, BX
CONT:
. . .
END:
. . .

这里我们对您进行了一些优化的例程:

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:

就是这样。现在回到(或前进?)这段小代码实际上做了什么。以下代码示例完全模仿您的示例,但适用于 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:

这是一个Long Multiplication algorithm

 12h = 00010010
               x
 34h = 01110100
       --------
       00000000
      01110100
     00000000
    00000000
   01110100
  00000000
 00000000
00000000

添加 34 小时平移两次:

0000000011101000
+
0000011101000000
----------------
0000011110101000 = 03A8

就是这样! 现在要使用更多数字,您可以使用相同的方法。下面是 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

干杯;)

关于assembly - 在 8086 微处理器上将 32 位两个数字相乘,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29246857/

相关文章:

arm - 是否有基于ARM的带有图形帧缓冲区的系统/仿真器,该缓冲区允许(相对)无遗留的Assembly编程?

python - 将多项式与 numpy.convolve 相乘返回错误结果

java - Java 中的 Fork Join 矩阵乘法

assembly - 8086 汇编中文本用户界面的字符大小错误

assembly - INT 16h/AH=0h 不等待引导加载程序中的按键

c - 将值从 C 程序传递到汇编语言

macos - OSX 64 位上的 NASM 问题

linux - 减去ESP或RSP寄存器会产生哪个异常? (堆栈增长)

c++ - 非方阵乘法帮助 C++

assembly - ISR 后程序不断返回同一行。 (总成 8086)