简介
由于8086只支持8位和16位的乘法,所以16位以上的乘法需要自己实现。该程序实现输入两个32位16进制数,计算乘积并分别用16进制和10进制输出计算结果。
程序运行结果
源代码
ASSUME CS:CODE1,DS:DATA1,SS:STACK1
STACK1 SEGMENT STACK
STACK_AREA DW 200H DUP(?)
STACK_BTM EQU $-STACK_AREA
STACK1 ENDS
DATA1 SEGMENT
EXPLAIN DB "please input 2 numbers in hex,separated by a blank symbol",10,13,'$'
NUMBER DD 1235H
ASCII DB 20H DUP(0)
TMP_QUOTIENT DD 0,0
TMP_REMAINDER DW 0,0
MUL1 DD 34H
MUL2 DD 12H
RESULT DD 2 DUP(0H)
DATA1 ENDS
CODE1 SEGMENT
MAIN PROC FAR
MOV AX,STACK1
MOV SS,AX
MOV SP,STACK_BTM
MOV AX,DATA1
MOV DS,AX
MOV DX,OFFSET EXPLAIN
MOV AH,09
INT 21H
MOV AX,OFFSET RESULT
PUSH AX
MOV AX,OFFSET MUL1
PUSH AX
MOV AX,OFFSET MUL2
PUSH AX
CALL MUL32
MOV AX,OFFSET MUL1
PUSH AX
CALL INPUT16
MOV AX,OFFSET MUL2
PUSH AX
CALL INPUT16
MOV AX,OFFSET RESULT
PUSH AX
MOV AX,OFFSET MUL1
PUSH AX
MOV AX,OFFSET MUL2
PUSH AX
CALL MUL32
MOV AX,OFFSET RESULT
PUSH AX
CALL OUTPUT16
MOV AX,OFFSET RESULT
PUSH AX
CALL OUTPUT10
MOV AX,4C00H
INT 21H
MAIN ENDP
MUL32 PROC NEAR ;[SP+2]a1 [SP+4]a2 [SP+6]res ;模拟二进制乘法的过程,用逻辑运算和加法实现乘法
PUSH SI
PUSH DI
PUSH ES
PUSH SP
PUSH AX
PUSH BX
PUSH CX
PUSH DX
MOV SI,SP
MOV SI,SS:[SI+18] ; addr a1
MOV BX,SP
MOV DI,SS:[BX+20] ;addr a2
MOV BP,[DI]
MOV DI,[DI+2] ;DI:BP=a2
MOV AX,32
MOV ES,AX
MOV AX,0
MOV BX,0
MOV CX,0
MOV DX,0
MUL_LOOP:
TEST BP,1
JZ SKIP_ADD
ADD CX,[SI]
ADC DX,[SI+2]
SKIP_ADD:
RCR DX,1
RCR CX,1
RCR BX,1
RCR AX,1
SHR DI,1
RCR BP,1
PUSH AX
MOV AX,ES
SUB AX,1
MOV ES,AX
POP AX
JNZ MUL_LOOP
MOV SI,SP
MOV SI,SS:[SI+22]
MOV [SI],AX
MOV [SI+2],BX
MOV [SI+4],CX
MOV [SI+6],DX
POP DX
POP CX
POP BX
POP AX
POP SP
POP ES
POP DI
POP SI
RET 6
MUL32 ENDP
INPUT16 PROC NEAR ; 读取一个32位的16进制数 [SP+2] 要存储到的内存地址
PUSH SI
PUSH AX
PUSH BX
PUSH CX
PUSH DX
MOV SI,SP
MOV SI,SS:[SI+12];num
MOV AX,0
MOV [SI],AX
MOV [SI+2],AX
MOV [SI+4],AX
MOV [SI+6],AX
INPUT16_LOOP:
MOV AH,01H
INT 21H
CMP AL,30H
JB NOT_NUM
CMP AL,39H
JA NOT_NUM
MOV BH,0
MOV BL,AL
SUB BX,30H
JMP INPUT16_RCL
NOT_NUM:
CMP AL,41H
JB NOT_ALP
CMP AL,46H
JA NOT_ALP
MOV BH,0
MOV BL,AL
SUB BX,41H
ADD BX,10
JMP INPUT16_RCL
INPUT16_RCL:
MOV CX,4
INPUT16_RCL_LOOP:
MOV AX,[SI]
SHL AX,1
MOV [SI],AX
MOV AX,[SI+2]
RCL AX,1
MOV [SI+2],AX
MOV AX,[SI+4]
RCL AX,1
MOV [SI+4],AX
MOV AX,[SI+6]
RCL AX,1
MOV [SI+6],AX
LOOP INPUT16_RCL_LOOP
MOV AX,[SI]
OR AX,BX
MOV [SI],AX
JMP INPUT16_LOOP
NOT_ALP:
POP DX
POP CX
POP BX
POP AX
POP SI
RET 2
INPUT16 ENDP
OUTPUT16 PROC NEAR ;按10进制输出一个64位数字 [SP+2]为存储数字的内存空间的首地址
PUSH AX
PUSH BX
PUSH CX
PUSH DX
PUSH SI
MOV BX,SP
MOV BX,SS:[BX+12]
MOV CX,16
OUTPUT_LOOP:
MOV SI,CX
DEC SI
SHR SI,1
MOV DL,[BX+SI]
TEST CX,1
JZ SKIP_SHL
SHL DL,1
SHL DL,1
SHL DL,1
SHL DL,1
SKIP_SHL:
SHR DL,1
SHR DL,1
SHR DL,1
SHR DL,1
CMP DL,10
JB OUTPUT_NUM
ADD DL,41H
SUB DL,10
JMP OUTPUT_FIN
OUTPUT_NUM:
ADD DL,30H
OUTPUT_FIN:
; MOV AH,02H
; INT 21H
MOV DI,OFFSET ASCII
ADD DI,CX
MOV [DI-1],DL
LOOP OUTPUT_LOOP
MOV CX,16
MOV BX,0
OUTPUT_LOOP_2:
MOV DI,OFFSET ASCII
ADD DI,CX
MOV DL,[DI-1]
MOV BH,DL
SUB BH,30H
OR BL,BH
JZ SKIP_OUTPUT16
MOV AH,02H
INT 21H
SKIP_OUTPUT16:
LOOP OUTPUT_LOOP_2
MOV DL,09H ;HORIZONTAL TAB
MOV AH,02H
INT 21H
POP SI
POP DX
POP CX
POP BX
POP AX
RET 2
OUTPUT16 ENDP
OUTPUT10 PROC NEAR ;按10进制输出一个64位数字 [SP+2]为存储数字的内存空间的首地址
PUSH AX
PUSH BX
PUSH CX
PUSH DX
PUSH SI
PUSH DI
MOV SI,SP
MOV SI,SS:[SI+14] ;num
MOV DI,OFFSET TMP_QUOTIENT
MOV AX,[SI]
MOV [DI],AX
MOV AX,[SI+2]
MOV [DI+2],AX
MOV AX,[SI+4]
MOV [DI+4],AX
MOV AX,[SI+6]
MOV [DI+6],AX
MOV CX,0
OUTPUT10_LOOP:
MOV AX,OFFSET TMP_REMAINDER
PUSH AX
MOV AX,OFFSET TMP_QUOTIENT
PUSH AX
PUSH AX
CALL DIVBY10
MOV DL,BYTE PTR TMP_REMAINDER
ADD DL,30H
MOV BX,OFFSET ASCII
ADD BX,CX
MOV [BX],DL
INC CX
MOV BX,OFFSET TMP_QUOTIENT
MOV AX,0
OR AX,[BX]
OR AX,[BX+2]
OR AX,[BX+4]
OR AX,[BX+6]
JNZ OUTPUT10_LOOP
OUTPUT10_LOOP_2:
MOV BX,OFFSET ASCII
ADD BX,CX
MOV DL,[BX-1]
MOV AH,2
INT 21H
LOOP OUTPUT10_LOOP_2
MOV DL,09H ;HORIZONTAL TAB
MOV AH,02H
INT 21H
POP DI
POP SI
POP DX
POP CX
POP BX
POP AX
RET 2
OUTPUT10 ENDP
DIVBY10 PROC NEAR ; SP:IP [SP+2]dst address [SP+4] src address [SP+6] dst shang
PUSH AX
PUSH BX
PUSH CX
PUSH DX
PUSH SI
PUSH DI
MOV BP,SP
MOV DI,[BP+14]
MOV SI,[BP+16]
MOV DX,0
MOV CX,10
MOV AX,[SI+6]
DIV CX
MOV [DI+6],AX
MOV AX,[SI+4]
DIV CX
MOV [DI+4],AX
MOV AX,[SI+2]
DIV CX
MOV [DI+2],AX
MOV AX,[SI]
DIV CX
MOV [DI],AX
MOV DI,[BP+18]
MOV [DI],DX
POP DI
POP SI
POP DX
POP CX
POP BX
POP AX
RET 6
DIVBY10 ENDP
CODE1 ENDS
END MAIN