我有在 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 位两个数字,我知道我需要如下更新:
- 将
AX
更改为00000002h
,将BX
更改为00000008h
。 - 再使用两个寄存器(我不知道应该使用哪个寄存器)来保存第二个和第三个16位乘法(因为乘法将是64位。16位乘法4次。我目前有DX和CX。)
- 将循环编号更新为
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
我的问题是:
- 如何处理一个 32 位数字的两个不同寄存器。 (寄存器是16位的,所以我必须将数字分成两个寄存器)
- 我可以使用哪些寄存器来实现此目的?我可以随意使用any注册吗?
提前致谢。
最佳答案
授人以鱼,然后等等……
很好,你有一个代码示例。但你了解算法吗?
好吧,让我们通过一个简化的例子一步一步地看一下:将 AL
和 AH
中的两个 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/