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 位两个数字,我知道我需要更新,例如:
AX到00000002h和BX到00000008h。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.
Run Code Online (Sandbox Code Playgroud)
资料来源:http : //www.electronics.dit.ie/staff/tscarff/8086_instruction_set/8086_instruction_set.html
我的问题是:
提前致谢。
给一个人一条鱼,等等等等……
很好,你有一个代码示例。但是你懂算法吗?
好了,让我们通过它一步一步上的简化的示例:在相乘两个8位寄存器AL和AH,并且将结果存储在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)
干杯;)
| 归档时间: |
|
| 查看次数: |
18284 次 |
| 最近记录: |