簡介
由于8086只支持8位和16位的乘法,所以16位以上的乘法需要自己實現。該程序實現輸入兩個32位16進制數,計算乘積并分別用16進制和10進制輸出計算結果。
程序運行結果
image.png
源代碼
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