Assembly 组装TASM:将4位数字乘以4位数字
我试图创建一个计算器程序使用汇编语言,但它是我们需要显示4位数字运算 在这段代码中,我可以加、减、除4位数字,但当4位数字乘以4位数字时,答案是不同的和错误的 示例:9999x9999=37601(这是错误的,答案应该是9998001) 下面是乘法代码的一部分:Assembly 组装TASM:将4位数字乘以4位数字,assembly,tasm,Assembly,Tasm,我试图创建一个计算器程序使用汇编语言,但它是我们需要显示4位数字运算 在这段代码中,我可以加、减、除4位数字,但当4位数字乘以4位数字时,答案是不同的和错误的 示例:9999x9999=37601(这是错误的,答案应该是9998001) 下面是乘法代码的一部分: 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 w
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
由于您希望显示乘法的完整32位结果(在DX:AX
),因此不能浪费DX
寄存器!您需要像使用AX
一样保留它因为您当前的转换/显示例程(为什么命名错误?)只知道16位数字,所以您需要另一个我将在下面介绍的例程。这个例行程序来自于。你一定要看。它非常详细地解释了这些东西是如何工作的,所以我不在这里重复这个解释
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
由于您希望显示乘法的完整32位结果(在DX:AX
),因此不能浪费DX
寄存器!您需要像使用AX
一样保留它因为您当前的转换/显示例程(为什么命名错误?)只知道16位数字,所以您需要另一个我将在下面介绍的例程。这个例行程序来自于。你一定要看。它非常详细地解释了这些东西是如何工作的,所以我不在这里重复这个解释
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
您确定您的作业要求您支持8位数的结果吗?明智的选择是生成低4位数字(即正确的结果模10k),但这仍然意味着您不能只让16位结果以模2^16进行包装。如果您确实需要完整的乘法结果,则16b x 16x=>32b乘法结果的高半部分是DX。i、 e.
mul bx
在dx:ax
中产生一个32位的结果。就在mul
指令之后,一对寄存器dx
和ax
保存总结果。您需要存储这两个寄存器,然后在打印前恢复它们,并在错误:
处调整输出代码,以输出存储在两个寄存器中的32位值,这一点很重要(将0x05F592E1
除以10
,使用类似div bx
的16b除法将导致除法溢出,因为结果不适合ax
)。或者确定是否可以使用32b寄存器(然后将所有算术运算转换为32b寄存器,如eax
),或搜索如何在x86-16中打印32b值。另一个选项是不使用二进制值进行计算,而是将它们保留为单独的数字(BCD Unpacket是存储值的选项之一)并且像纸上一样用单独的数字来做所有的算术运算。还要确保你理解为什么我们在这些16/32位的注释上乱动,以及为什么你的结果从16b计算的角度来看是正确的。要了解如何在DX:AX
中显示你的产品,请阅读这篇优秀的Q/A。你确定你的作业要求吗您是否支持8位数的结果?明智的选择是生成低4位数(即正确的结果模10k),但这仍然意味着您不能只让16位结果以模2^16进行包装。如果您确实需要完整的乘法结果,则16b x 16x=>32b乘法结果的上半部分是DX。即,mul bx
在DX:ax
中生成32位结果。就在mul
指令之后,一对寄存器DX
和ax
保留总结果。您需要存储这两个结果,然后在打印前还原它们,并在错误:
处调整输出代码,以输出存储在两个寄存器中的32位值,这一点很重要(将0x05F592E1
除以10
,使用类似div bx
的16b除法将导致除法溢出,因为结果不适合ax
)。或者确定是否可以使用32b寄存器(然后将所有算术运算转换为32b寄存器,如eax
),或搜索如何在x86-16中打印32b值。另一个选项是不使用二进制值进行计算,而是将它们保留为单独的数字(BCD Unpacket是存储值的选项之一)并且像纸上一样用单独的数字做所有的算术运算。还要确保你理解为什么我们要在那些16/32位的注释上乱来,以及为什么你的结果从16b计算的角度来看是正确的。要了解如何在DX:AX
中显示你的产品,请阅读这篇优秀的Q/A。这篇文章内容非常丰富!仅此而已回答,我能做得很好!谢谢你,先生!这是非常有用的!只有这个答案,我能做得很好!谢谢你,先生!