Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/assembly/6.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Assembly 组装TASM:将4位数字乘以4位数字_Assembly_Tasm - Fatal编程技术网

Assembly 组装TASM:将4位数字乘以4位数字

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

我试图创建一个计算器程序使用汇编语言,但它是我们需要显示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 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。这篇文章内容非常丰富!仅此而已回答,我能做得很好!谢谢你,先生!这是非常有用的!只有这个答案,我能做得很好!谢谢你,先生!