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

时间:2017-12-02 16:18:50

标签: assembly

我对算术运算如何适用于4位数字感到困惑。这是我正在进行的决赛项目。

我真的很努力去理解大会所以请原谅我,如果我不能正确回答你的问题,但这是我们用于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

1 个答案:

答案 0 :(得分:2)

您需要首先研究如何以位为单位编码整数值,即二进制编码:https://en.wikipedia.org/wiki/Binary_number(这是了解我的答案和问题的必要先决条件)。

  

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

输入 ASCII字符。它从 转换为0..9(如果是有效输入,则为ASCII数字)。因为例如ASCII字符'2'的值为5032h),所以在sub al,48之后你有al2(不再有字符) ,但整数值,以二进制编码)。

...到目前为止,你设法得到了至少一件事,即用户有一些输入。其他一切都搞砸了。如果你想在汇编代码中进行编码,你必须更精确,机器永远不会猜到你做了什么想要,它总会按照你在代码中要求的那样做。如果你不精确,它会做你不想要的事情。

  

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

是的,第一个数字值乘以16.这是小猫死亡的部分,因为您使用mul乘以2的幂,而不是使用左移4位{{1} }。这是相同的,乘以16,因为2 4 = 16(如果你理解二进制数,你应该能够弄清楚,为什么左移位是乘以2)。

  

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

您的原始来源使用两位数值的packed-BCD编码。

第一个数字"数十"占据前4位,第二位" 1"占用低4位。即用户输入" 34"生成的二进制值为shl al,4 2 = 3 * 16 + 4 = 0011 0100(十进制)或52(十六进制)。

对于两个BCD数字,您需要8位。您的旧代码确实将BCD值计算为34h(8位寄存器),并将其存储在al地址的存储器中,其中保留单个字节(8位)。

然后当两个值都在内存中并且第二个数字在NUM1时,代码执行:

AL

它首先使用BCD值执行普通二进制ADD AL, [NUM1] DAA ADD [SUM], AL 。如果第二个输入为" 18",那么ADD发生add 18h, 34h,这是非法的BCD值,因为第一个数字是AL = 4Ch(OK),第二个数字是4(非法)。

然后下一条指令DAA "Decimal adjust AL after Addition"会将结果修复回有效的BCD,即12(十进制AL = 52h,二进制82),其中第一个BCD数字为5,并且第二个是2.在人类的十进制方式中,这就是你想要的,因为18 + 34 = 52。

最后生成的BCD总和被0101 0010添加到未初始化的内存SUM,技术上是另一个错误,虽然在正常情况下内存包含零值,所以它偶然起作用(我写过你了吗?已经,你必须在汇编中精确吗?)。

稍后你会有一些说明:

ADD [SUM], AL

那是第二只死去的小猫,你是一个怪物。实际上{16}计算MOV BL, 10000B ; mov bl,16 DIV BL 就像两只死小猫一样(而且我很慷慨,因为divDIV慢约5-10倍,不仅慢两倍,所以总数是3.将无符号整数除以16的有效方法是MUL

shr al,4

这甚至不是有效的x86指令。无论你使用哪种汇编程序,都要快速远离它。 (我强烈怀疑这是emu8086,我个人认为这非常恶劣,因为像这样的事情,emu8086通常会将任何随机文本组装成某些 x86指令,所以除非你经常调试你的代码有了反汇编视图,你甚至不知道你正在使用什么指令。

如何将其扩展为4位数:

1)清理当前版本,删除LEA DL, AL 16。删除复制/粘贴冗余代码,将其转换为程序,使用如下:

mul/div

然后你只需要单个代码就可以从用户那里读取两个字符,并将它们转换为BCD。调试它更正确,比如不要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 执行未初始化的内存,而是ADD进行设置,而不是mov [SUM],al

2)4个BCD打包数字需要16位存储空间。每个数字是4位= 4x4 = 16.(即当4位数值" 1234"位于add时,ax的值为ax = {{ 1}} 2 = 1234h十进制。

因此,您需要将所有内存预留从字节更改为单词(0001 0010 0011 0100)。然后,您需要将所有寄存器从8位寄存器(如4660)更改为16位寄存器,如NUM1 DW ?

当然,如果您只是在当前代码中盲目地将al替换为ax,那么它将无效,因为al将完全失败,等等......如果您这样做了按照1)的建议进行适当的清理,你会有一点简单,你仍需要检查每条指令,并以16b的方式修复它,重写代码的某些部分。

例如,可以循环读取用户输入,选择一些备用16b寄存器来累加值,将其重置为零,然后执行4次"读取字符,将其转换为0-9值,移位当前结果为4位,ax输入值为最低4位" - >结果是4位数的BCD值。

16位mul/div没有OR,因此您应该按字节加DAA,按ax解析每个加法,再加上处理CF的时间示例num1+num2。 =很多代码,但这是你的选择,以BCD打包的方式存储值,而不是本机二进制。

从头开始,我猜代码就像:

DAA

你绝对应该首先在纸上做所有的数学运算,只需要几个示例输入(并将所有3种格式记录在一起,二进制,六进制和十进制,尝试将它们转换为头,你需要练习一下,到能够告诉CPU如何使用CPU位,因此您可以稍后调试代码并检查所有位是否包含预期的结果(来自纸张)。

然后在理解了背后的数学之后,直接在代码中编写它。您应该准确了解每条指令的作用,以及将其添加到代码中的原因。

然后你可以在调试器中验证它。慢慢地,每一条指令,验证它是否真的,你需要什么。

还要考虑抛弃整个BCD打包方案,并使用相当原生的二进制数。然后你可以添加任何4位数值,甚至是5位数的值,因为9999 + 9999 = 19998,这将适合16位(0..65535)。对于5到9位数字,您将需要32位数学。