组装 TASM:将 4 位数字乘以 4 位数字
Assembly TASM: Multiply 4 digit numbers by 4 digit numbers
我正在尝试使用汇编语言创建一个计算器程序,但我们需要它来显示 4 位数字运算。
在这段代码中,我可以对每个 4 位数字进行加、减和除,但是当将 4 位数字乘以 4 位数字时,答案不同且错误
示例:9999x9999= 37601(错误,答案应为 99980001)
下面是乘法部分的代码:
mult:
pop ax
mul bx
push ax
lea dx,Mulseu
mov ah,09h
int 21h
pop ax
mov cx,0
mov dx,0
mov bx,10d
jmp wrong
完整代码如下:
.model small
.stack 100h
.data
msg1 db 13, 10, 13, 10,"MENU "
db 10, 13,"1. Add "
db 10, 13,"2. Subtract "
db 10, 13,"3. Multiply "
db 10, 13,"4. Divide "
db 10, 13,"5. Exit "
db 13,10,13,10, "Enter 1st Number : $"
msg2 db 13,10, "Enter 2nd Number : $"
msgEr db 13,10, "Error $"
choiceseu db 13,10, "Enter choice: $ "
sumseu db 13,10,13,10, "***Sum is : $"
Diffseu db 13,10,13,10, "***Difference is : $"
Divseu db 13,10,13,10, "***Quotient is : $"
Mulseu db 13,10,13,10, "***Product is : $"
temp db ?
.code
start:
mov ax, @data
mov ds, ax
lea dx, msg1
mov ah, 09h
int 21h
mov bx, 0
ph1:
mov ah, 01h
int 21h
cmp al,0dh
je input1
mov ah,0
sub al,30h
push ax
mov ax,10d
mul bx
pop bx
add bx,ax
jmp ph1
input1:
push bx
lea dx,msg2
mov ah,09h
int 21h
mov bx,0
ph2:
mov ah,01h
int 21h
cmp al,0dh
je choice
mov ah,0
sub al,30h
push ax
mov ax,10d
mul bx
pop bx
add bx,ax
jmp ph2
choice:
lea dx, choiceseu
mov ah, 09h
int 21h
mov ah, 01h
int 21h
cmp al,'4'
je divd
cmp al,'1'
je addz
cmp al,'2'
je subt
cmp al,'3'
je mult
cmp al,'5'
mov ah, 4ch
int 21h
error:
lea dx,msgEr
mov ah,09h
int 21h
jmp start
divd:
pop ax
mov dx, 0
div bx
push ax
lea dx,Divseu
mov ah,09h
int 21h
pop ax
mov cx,0
mov dx,0
mov bx,10d
jmp wrong
addz:
pop ax
add ax,bx
push ax
lea dx,sumseu
mov ah,09h
int 21h
pop ax
mov cx,0
mov dx,0
mov bx,10d
jmp wrong
mult:
pop ax
mul bx
push ax
lea dx,Mulseu
mov ah,09h
int 21h
pop ax
mov cx,0
mov dx,0
mov bx,10d
jmp wrong
subt:
pop ax
sub ax,bx
push ax
lea dx,Diffseu
mov ah,09h
int 21h
pop ax
mov cx,0
mov dx,0
mov bx,10d
wrong:
mov dx, 0
div bx
push dx
mov dx,0
inc cx
or ax,ax
jne wrong
ans:
pop dx
add dl,30h
mov ah,02h
int 21h
loop ans
jmp start
end start
mult:
pop ax
mul bx
push ax
lea dx,Mulseu
mov ah,09h
int 21h
pop ax
mov cx,0
mov dx,0
mov bx,10d
jmp wrong
既然要显示乘法的完整 32 位结果(在 DX:AX
中),就不能让 DX
寄存器白白浪费!您需要像 AX
.
一样保存它
因为您当前的 conversion/displaying 例程(为什么 o 为什么这个命名为 错误 ?)只知道 16 位数字,您将需要我将在下面介绍的另一个例程。本套路来自another answer that I wrote some time ago。你绝对应该阅读它。它非常详细地解释了这些东西是如何工作的,所以我不会在这里重复那个解释。
mult:
pop ax
mul bx
push ax
push dx
lea dx, Mulseu
mov ah, 09h
int 21h
pop dx
pop ax
jmp DisplayNumber32
...
DisplayNumber32:
mov bx,10 ;CONST
push bx ;Sentinel
.a: mov cx,ax ;Temporarily store LowDividend in CX
mov ax,dx ;First divide the HighDividend
xor dx,dx ;Setup for division DX:AX / BX
div bx ; -> AX is HighQuotient, Remainder is re-used
xchg ax,cx ;Temporarily move it to CX restoring LowDividend
div bx ; -> AX is LowQuotient, Remainder DX=[0,9]
push dx ;(1) Save remainder for now
mov dx,cx ;Build true 32-bit quotient in DX:AX
or cx,ax ;Is the true 32-bit quotient zero?
jnz .a ;No, use as next dividend
pop dx ;(1a) First pop (Is digit for sure)
.b: add dl,"0" ;Turn into character [0,9] -> ["0","9"]
mov ah,02h ;DOS.DisplayCharacter
int 21h ; -> AL
pop dx ;(1b) All remaining pops
cmp dx,bx ;Was it the sentinel?
jb .b ;Not yet
对于所有剩余的操作(addz、subt、divd)你也可以使用这个新的 DisplayNumber32 例程。只需确保事先将 DX
寄存器归零即可。
subt:
pop ax
sub ax, bx
push ax
lea dx, Diffseu
mov ah, 09h
int 21h
pop ax
xor dx, dx ;Add this for the 32-bit version!
jmp DisplayNumber32
我正在尝试使用汇编语言创建一个计算器程序,但我们需要它来显示 4 位数字运算。
在这段代码中,我可以对每个 4 位数字进行加、减和除,但是当将 4 位数字乘以 4 位数字时,答案不同且错误
示例:9999x9999= 37601(错误,答案应为 99980001)
下面是乘法部分的代码:
mult:
pop ax
mul bx
push ax
lea dx,Mulseu
mov ah,09h
int 21h
pop ax
mov cx,0
mov dx,0
mov bx,10d
jmp wrong
完整代码如下:
.model small
.stack 100h
.data
msg1 db 13, 10, 13, 10,"MENU "
db 10, 13,"1. Add "
db 10, 13,"2. Subtract "
db 10, 13,"3. Multiply "
db 10, 13,"4. Divide "
db 10, 13,"5. Exit "
db 13,10,13,10, "Enter 1st Number : $"
msg2 db 13,10, "Enter 2nd Number : $"
msgEr db 13,10, "Error $"
choiceseu db 13,10, "Enter choice: $ "
sumseu db 13,10,13,10, "***Sum is : $"
Diffseu db 13,10,13,10, "***Difference is : $"
Divseu db 13,10,13,10, "***Quotient is : $"
Mulseu db 13,10,13,10, "***Product is : $"
temp db ?
.code
start:
mov ax, @data
mov ds, ax
lea dx, msg1
mov ah, 09h
int 21h
mov bx, 0
ph1:
mov ah, 01h
int 21h
cmp al,0dh
je input1
mov ah,0
sub al,30h
push ax
mov ax,10d
mul bx
pop bx
add bx,ax
jmp ph1
input1:
push bx
lea dx,msg2
mov ah,09h
int 21h
mov bx,0
ph2:
mov ah,01h
int 21h
cmp al,0dh
je choice
mov ah,0
sub al,30h
push ax
mov ax,10d
mul bx
pop bx
add bx,ax
jmp ph2
choice:
lea dx, choiceseu
mov ah, 09h
int 21h
mov ah, 01h
int 21h
cmp al,'4'
je divd
cmp al,'1'
je addz
cmp al,'2'
je subt
cmp al,'3'
je mult
cmp al,'5'
mov ah, 4ch
int 21h
error:
lea dx,msgEr
mov ah,09h
int 21h
jmp start
divd:
pop ax
mov dx, 0
div bx
push ax
lea dx,Divseu
mov ah,09h
int 21h
pop ax
mov cx,0
mov dx,0
mov bx,10d
jmp wrong
addz:
pop ax
add ax,bx
push ax
lea dx,sumseu
mov ah,09h
int 21h
pop ax
mov cx,0
mov dx,0
mov bx,10d
jmp wrong
mult:
pop ax
mul bx
push ax
lea dx,Mulseu
mov ah,09h
int 21h
pop ax
mov cx,0
mov dx,0
mov bx,10d
jmp wrong
subt:
pop ax
sub ax,bx
push ax
lea dx,Diffseu
mov ah,09h
int 21h
pop ax
mov cx,0
mov dx,0
mov bx,10d
wrong:
mov dx, 0
div bx
push dx
mov dx,0
inc cx
or ax,ax
jne wrong
ans:
pop dx
add dl,30h
mov ah,02h
int 21h
loop ans
jmp start
end start
mult: pop ax mul bx push ax lea dx,Mulseu mov ah,09h int 21h pop ax mov cx,0 mov dx,0 mov bx,10d jmp wrong
既然要显示乘法的完整 32 位结果(在 DX:AX
中),就不能让 DX
寄存器白白浪费!您需要像 AX
.
一样保存它
因为您当前的 conversion/displaying 例程(为什么 o 为什么这个命名为 错误 ?)只知道 16 位数字,您将需要我将在下面介绍的另一个例程。本套路来自another answer that I wrote some time ago。你绝对应该阅读它。它非常详细地解释了这些东西是如何工作的,所以我不会在这里重复那个解释。
mult:
pop ax
mul bx
push ax
push dx
lea dx, Mulseu
mov ah, 09h
int 21h
pop dx
pop ax
jmp DisplayNumber32
...
DisplayNumber32:
mov bx,10 ;CONST
push bx ;Sentinel
.a: mov cx,ax ;Temporarily store LowDividend in CX
mov ax,dx ;First divide the HighDividend
xor dx,dx ;Setup for division DX:AX / BX
div bx ; -> AX is HighQuotient, Remainder is re-used
xchg ax,cx ;Temporarily move it to CX restoring LowDividend
div bx ; -> AX is LowQuotient, Remainder DX=[0,9]
push dx ;(1) Save remainder for now
mov dx,cx ;Build true 32-bit quotient in DX:AX
or cx,ax ;Is the true 32-bit quotient zero?
jnz .a ;No, use as next dividend
pop dx ;(1a) First pop (Is digit for sure)
.b: add dl,"0" ;Turn into character [0,9] -> ["0","9"]
mov ah,02h ;DOS.DisplayCharacter
int 21h ; -> AL
pop dx ;(1b) All remaining pops
cmp dx,bx ;Was it the sentinel?
jb .b ;Not yet
对于所有剩余的操作(addz、subt、divd)你也可以使用这个新的 DisplayNumber32 例程。只需确保事先将 DX
寄存器归零即可。
subt:
pop ax
sub ax, bx
push ax
lea dx, Diffseu
mov ah, 09h
int 21h
pop ax
xor dx, dx ;Add this for the 32-bit version!
jmp DisplayNumber32