【发布时间】:2017-10-20 07:34:35
【问题描述】:
我正在尝试使用汇编语言创建一个计算器程序,但我们需要显示 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
【问题讨论】:
-
您确定您的作业要求您支持 8 位结果吗?明智的选择是产生低 4 位数字(即正确的结果以 10k 为模),但这仍然意味着您不能只让 16 位结果以 2^16 为模。
-
如果您确实需要完整的乘法结果,则 16b x 16x => 32b 乘法结果的高半部分在 DX 中。即
mul bx在dx:ax中生成 32 位结果。 -
在
mul指令之后,一对寄存器dx和ax保存总结果。您需要存储两者,然后在打印前恢复它们,并在wrong:调整您的输出代码以输出存储在两个寄存器中的32 位值,这不是微不足道的(将0x05F592E1除以10与@987654332 之类的16b 除法@ 会导致除法溢出,因为结果不适合ax)。要么弄清楚你是否可以使用 32b 寄存器(然后将所有算术转换为 32b regs,比如eax),要么搜索如何在 x86-16 中打印 32b 值。 -
其他选项是不使用二进制值进行计算,而是将它们保留为单独的数字(BCD 解包是存储值的选项之一),并像在纸上一样使用单独的数字进行所有算术运算。还要确保您理解我们为什么要折腾那些 16/32 位注释,以及为什么从 16b 计算的角度来看,您的问题结果是有点正确。
-
要了解如何在
DX:AX中展示您的产品,请阅读这篇出色的 Q/A Displaying numbers with DOS。