Assembly 如何在汇编中对4位数字进行算术运算?

Assembly 如何在汇编中对4位数字进行算术运算?,assembly,Assembly,我对四位数的算术运算感到困惑。这是我正在做的期末考试项目 我真的在努力理解汇编,所以如果我不能正确回答您的问题,请原谅我,但这是我们用于2位输入算术运算的代码。我想知道当输入为4位数字时我如何使用它 .MODEL SMALL .STACK 200 .DATA RADIX DB 10 TEMP DB 10 DUP(?) CRLF DB 0DH,0AH,'$' PROMPT1 DB 'Input the 1st 2digit number: ',

我对四位数的算术运算感到困惑。这是我正在做的期末考试项目

我真的在努力理解汇编,所以如果我不能正确回答您的问题,请原谅我,但这是我们用于2位输入算术运算的代码。我想知道当输入为4位数字时我如何使用它

.MODEL SMALL
.STACK 200
.DATA 
    RADIX DB 10     
    TEMP DB 10 DUP(?)
    CRLF    DB  0DH,0AH,'$'
    PROMPT1 DB  'Input the 1st 2digit number: ','$'
    PROMPT2 DB  'Input the 2nd 2digit number: ','$'
    PROMPT3 DB  'The sum of two numbers is: ','$' 
    PROMPT4 DB  'The difference of two numbers is: ','$'
    PROMPT5 DB  'The product of two numbers is: ','$'
    PROMPT6 DB  'The quotient of two numbers is: ','$'
    PROMPT7 DB  'The remainder of two numbers is: ','$'
    NUM1    DB  ?
    NUM2    DB  ? 
    NUM3    DB  ?
    SUM     DB  ?  
    DIFF    DB  ?
    PROD    DB  ?
    QUO     DB  ?
    REM     DB  ?    

.CODE
.STARTUP
    LEA DX,PROMPT1 
    MOV AH,09H      
    INT 21H 

    MOV AH, 01H
    INT 21H
    SUB AL, 30H
    MOV CH, AL 
    MOV AH, 01H
    INT 21H

    SUB AL, 30H
    MOV CL, AL 
    MOV AL, 10000B 
    MUL CH 
    XOR AH, AH
    OR AL, CL   
    MOV NUM1, AL
    MOV AL, 00H 

    LEA DX,CRLF
    MOV AH,09H
    INT 21H 

    LEA DX,PROMPT2
    MOV AH,09H
    INT 21H  

    MOV AH, 01H
    INT 21H
    SUB AL, 30H
    MOV CH, AL 
    MOV AH, 01H
    INT 21H

    SUB AL, 30H
    MOV CL, AL 
    MOV AL, 10000B 
    MUL CH 
    XOR AH, AH 
    OR AL, CL   
    MOV NUM2, AL

    ADD AL, NUM1 
    DAA
    ADD SUM, AL  

    LEA DX,CRLF
    MOV AH,09H
    INT 21H 

    LEA DX,PROMPT3
    MOV AH,09H
    INT 21H


    MOV AL, SUM 
    XOR AH, AH
    MOV BL, 10000B
    DIV BL
    AND AL, 0FH 
    ADD AL, 30H 

    LEA DL, AL  
    MOV AH, 02H
    INT 21H

    MOV AL, SUM
    XOR AH, AH   
    AND AL, 0FH
    ADD AL, 30H 

    LEA DL, AL
    MOV AH,02H   
    INT 21H  

    MOV AL,00H
    MOV AL,NUM1
    SUB AL,NUM2
    DAS
    MOV DIFF,AL 

    LEA DX,CRLF
    MOV AH,09H
    INT 21H

    LEA DX,PROMPT4
    MOV AH,09H
    INT 21H

    MOV AL, DIFF 
    XOR AH, AH 
    MOV BL, 10000B
    DIV BL 
    AND AL, 0FH
    ADD AL, 30H

    LEA DL, AL  
    MOV AH, 02H
    INT 21H

    MOV AL, DIFF 
    XOR AH, AH  
    AND AL, 0FH
    ADD AL, 30H

    LEA DL, AL
    MOV AH,02H     
    INT 21H                

    LEA DX,CRLF
    MOV AH,09H
    INT 21H

    LEA DX,PROMPT5
    MOV AH,09H
    INT 21H

    MOV AL, 00H
    MOV DL, 00H
    MOV AL, NUM1
    MOV DL, NUM2
    MUL DL 

    MOV PROD, AL   

    MOV CX, 00H 
    XOR BH, BH 
    XOR SI, SI   

    DISPX1:
    MOV DX, 00 
    DIV BX 
    MOV TEMP[SI], DL 
    INC SI
    INC CX 
    OR AX, AX 
    JNZ DISPX1
    DEC SI

    MOV AL, PROD
    DISPX2:
    MOV DL, TEMP [SI]
    MOV AH, 06H 
    ADD DL, 30H 
    INT 21H
    DEC SI
    DEC CX 
    JNZ DISPX2        

    MOV AX,00H 
    MOV BX,00H
    MOV AL,NUM1
    MOV BH,NUM2
    DIV BH
    MOV QUO,AL 
    MOV REM,AH

    LEA DX,CRLF
    MOV AH,09H
    INT 21H

    LEA DX,PROMPT6
    MOV AH,09H
    INT 21H

    MOV AL, QUO
    XOR AH, AH 
    MOV BL, 10000B
    DIV BL 
    AND AL, 0FH
    ADD AL, 30H

    LEA DL, AL 
    MOV AH, 02H 
    INT 21H

    MOV AL, QUO 
    XOR AH, AH 
    AND AL, 0FH
    ADD AL, 30H

    LEA DL, AL
    MOV AH,02H  
    INT 21H   

    LEA DX,CRLF
    MOV AH,09H
    INT 21H

    LEA DX,PROMPT7
    MOV AH,09H
    INT 21H     

    MOV AL, REM 
    XOR AH, AH 
    MOV BL, 10000B
    DIV BL 
    AND AL, 0FH 
    ADD AL, 30H 

    LEA DL, AL  
    MOV AH, 02H 
    INT 21H

    MOV AL, REM 
    XOR AH, AH   
    AND AL, 0FH
    ADD AL, 30H

    LEA DL, AL
    MOV AH,02H   
    INT 21H               

.EXIT                 
END

您需要首先研究整数值如何以位进行编码,即二进制编码:(这是理解我的答案和您的问题的必要先决条件)

该代码要求用户输入一个数字,该数字将转换为ASCII码

输入为ASCII字符。它从ASCII转换为
0..9
(如果输入有效,则转换为ASCII数字)。因为例如ASCII字符
'2'
具有值
50
32h
),所以在
sub al之后,48
中有
al
2
(没有更多字符,而是二进制编码的整数值)

。。。到目前为止,至少有一件事是正确的,那个就是用户提供了一些输入。其他一切都搞砸了。如果你想在汇编中编写代码,你必须更加精确,机器永远不会猜到你想要什么,它总是按照你在代码中要求的去做。如果你不精确,它会做你不想做的事情

然后第一个数字是十,所以它乘以10000B

是的,第一个数字值乘以16。这是小猫死亡的部分,因为您使用了
mul
乘以二的幂,而不是使用左移位4位
shl al,4
。这和乘以16是一样的,因为24=16(如果你理解二进制数,你应该能够理解,为什么向左移位的位乘以2的幂)

这是我很难理解的部分。当你需要4位数字时,你在哪里乘法

您的原始源代码使用两位数的编码

第一位数字“十”占据前4位,第二位数字“一”占据低4位。即,对于用户输入“34”,结果二进制值为十进制的
0010100
2=3*16+4=
52
,或十六进制的
34h

对于两个BCD数字,需要8位。您的旧代码将BCD值计算到
al
(8位寄存器)中,并将其存储到
NUM1
地址的内存中,其中保留了一个字节(8位)

然后,当两个值都在内存中且第二个数字在
AL
中时,代码执行以下操作:

ADD AL, [NUM1] 
DAA
ADD [SUM], AL  
它首先使用BCD值添加普通二进制
。如果第二个输入为“18”,则会出现
add 18h、34h
,并且
AL=4Ch
,这是非法的BCD值,因为第一个数字是
4
(确定),第二个数字是
12
(非法)

然后,下一条指令将把结果修复回有效的BCD,即
AL=52h
(十进制
82
,二进制
01010010
),其中第一个BCD数字是5,第二个是2。以人类十进制的方式,这就是你想要的,因为18+34=52

最后,通过
ADD[sum],AL
将生成的BCD和添加到未初始化的内存
sum
,这在技术上是另一个错误,尽管在正常情况下,内存包含零值,所以它是偶然工作的(我是否已经写给你了,你必须在汇编中精确

随后,您将获得以下几条说明:

MOV BL, 10000B      ; mov bl,16
DIV BL
那是第二只死猫,你是个怪物。实际上,
div
比两只死小猫慢了16次(我很慷慨,因为
div
MUL
慢了5-10倍,不仅慢了两倍),所以总数是3。将无符号整数除以16的有效方法是
shral,4


这甚至不是有效的x86指令。不管你用的是什么汇编程序,赶快离开它。(我强烈怀疑这就是emu8086,我个人认为它非常残暴,因为这样的事情,emu8086通常会将任何随机文本汇编成一些x86指令,因此除非您使用反汇编视图大量调试代码,否则您甚至不知道您使用的是什么指令)


如何将其扩展到4位:

1) 清除当前版本,按16删除
mul/div
。删除复制/粘贴冗余代码,将其转换为过程,以便像以下那样使用:

call getInputValue   ; returns two digit BCD in AL
mov  [NUM1],al       ; NUM1 from user
call getInputValue   ; returns two digit BCD in AL
mov  [NUM2],al       ; NUM2 from user
然后,您只需要一个代码就可以从用户处读取两个字符,并将它们转换为BCD。调试它以使其更加正确,例如不要将
添加到未初始化的内存中,而是执行
mov[SUM],al
来设置它,而不是
添加

2) 4 BCD压缩数字需要16位存储。每个数字为4位=4x4=16。(即,当4位数字值“1234”位于
ax
时,
ax
的值为
1234h
=
0001 0010 0011 0100
2=
4660
十进制

因此,您需要将所有内存保留从字节更改为字(
num1dw?
),然后需要将所有寄存器从8位寄存器(如
al
)更改为16位寄存器(如
ax

当然,如果您在当前代码中盲目地将
al
替换为
ax
,它将不起作用,因为
mul/div
将完全失败,等等。如果您按照1)中的建议进行了适当的清理,您的操作会简单一点,仍然需要检查每个指令,并以16b的方式修复它,重写部分代码

例如,用户输入可以在循环中读取,选择一些备用16b寄存器累积值,将其重置为零,然后执行4次“读取字符,将其转换为0-9值,将当前结果左移4位,
输入值为最低4位”->结果是4位压缩BCD值

没有
DAAcall getInputValue   ; returns two digit BCD in AL
mov  [NUM1],al       ; NUM1 from user
call getInputValue   ; returns two digit BCD in AL
mov  [NUM2],al       ; NUM2 from user
mov al,[NUM1]
add al,[NUM2]   ; add low 2 digits of NUM1 and NUM2
daa             ; bcd fix
mov [SUM],al    ; store low 2 digits
mov al,[NUM1+1]
adc al,0        ; add CF to upper 2 digits
daa             ; bcd fix
jc  addOverflow_needs5digits  ; when result is > 9999
add al,[NUM2+1] ; add upper two digits of NUM2
daa             ; bcd fix
mov [SUM+1],al  ; store upper 2 digits
jc  addOverflow_needs5digits  ; when result is > 9999
; all those DW accessed by AL may need "BYTE PTR" override in MASM