原有的乘法指令是8位乘法或16位乘法,对于32位的大数乘法还是要自己去实现的。其实思路也不难,类比考虑两位数十进制乘法:(10A + B) X (10C + D) = 100 AC + 10BC + 10 AD + BD
那么我们要实现的就是四次16进制的乘法和将其结果相加:
目标为NUM_A: NUM_B X NUM_C :NUM_D -> RESULT_H:RESULT_MH: RESULT_ML:RESULT_L
可以分解为
NUM_B X NUM_D -> RESULT_ML:RESULT_L
NUM_A X NUM_C -> RESULT_H:RESULT_MH
RESULT_MH : RESULT_ML += NUM_B X NUM_C
RESULT_MH : RESULT_ML += NUM_A X NUM_D
初步形成代码:
;实现32位大数乘法
;(10A + B) x (10C + D) = 100AC + 10(AD + BC) + BD
STACK SEGMENT PARA STACK
STACK_AREA DW 100H DUP(0)
STACK ENDS
DATA SEGMENT PARA
NUM_A DW 1234H
NUM_B DW 5678H
NUM_C DW 8765H
NUM_D DW 4321H
RESULT_H DW 0
RESULT_MH DW 0
RESULT_ML DW 0
RESULT_L DW 0
DATA ENDS
CODE SEGMENT PARA
ASSUME CS:CODE,DS:DATA,SS:STACK
MAIN PROC FAR
MOV AX,DATA
MOV DS,AX
MOV AX,NUM_B
MOV BX,NUM_D
MUL BX
MOV RESULT_ML,DX
MOV RESULT_L,AX
MOV AX,NUM_A
MOV BX,NUM_C
MUL BX
MOV RESULT_H,DX
MOV RESULT_MH,AX
MOV AX,NUM_A
MOV BX,NUM_D
MUL BX
ADD DX,RESULT_MH
ADD AX,RESULT_ML
MOV RESULT_MH,DX
MOV RESULT_ML,AX
MOV AX,NUM_B
MOV BX,NUM_C
MUL BX
ADD DX,RESULT_MH
ADD AX,RESULT_ML
MOV RESULT_MH,DX
MOV RESULT_ML,AX
EXIT: MOV AX,4C00H
INT 21H
MAIN ENDP
CODE ENDS
END MAIN
进行测试
然而,使用windows自带的计算器进行对照,可以算出
12345678H X 87654321H = 09A0_CD05_70B8_8D78H
有一位出现了错误
说明上述代码我们忽视了一个问题,大数运算的进位,运算过程中,16位数的乘法最高为32位,而16位数的加法则有可能产生17位数,因此再每次做加法之后都必须考虑进位的问题
使用ADC可以解决这个问题,但是要注意的是,ADC加法仍然可能又一次产生进位,所以也需要一次检验想清楚了以上几点,修改MAIN函数如下
MAIN PROC FAR
MOV AX,DATA
MOV DS,AX
MOV AX,NUM_A
MOV BX,NUM_C
MUL BX
MOV RESULT_H,DX
MOV RESULT_MH,AX
MOV AX,NUM_B
MOV BX,NUM_D
MUL BX
MOV RESULT_ML,DX
MOV RESULT_L,AX
MOV AX,NUM_A
MOV BX,NUM_D
MUL BX
ADD AX,RESULT_ML
MOV RESULT_ML,AX
ADC RESULT_MH,0
ADC RESULT_H,0
ADD DX,RESULT_MH
MOV RESULT_MH,DX
ADC RESULT_H,0
MOV AX,NUM_B
MOV BX,NUM_C
MUL BX
ADD AX,RESULT_ML
MOV RESULT_ML,AX
ADC RESULT_MH,0
ADC RESULT_H,0
ADD DX,RESULT_MH
MOV RESULT_MH,DX
ADC RESULT_H,0
EXIT: MOV AX,4C00H
INT 21H
MAIN ENDP
我们改正代码后,查看内存算出的结果:
结果完全吻合
NEXT:串操作