微机原理实验2:多字节BCD加法实验

一、实验目的

掌握数据传送、算术指令和循环指令的用法。

二、实验内容

将两个多位十进制数相加。要求加数,被加数均以ASCII码形式存放在以DATA1和DATA2为首的5个内存单元中( 低位在前),结果存在DATA1处。

三、程序清单

CRLF    MACRO                           ;建立宏命令,利用INT中断实现回车换行的功能,方便后续直接调用
        MOV     DL,0DH
        MOV     AH,02H
        INT     21H                     ;光标移到第一列
        MOV     DL,0AH
        MOV     AH,02H
        INT     21H                     ;光标移到下一行
ENDM

DATA    SEGMENT
DATA1   DB      33H,39H,31H,37H,34H     ;被加数ASCII码
DATA2   DB      36H,35H,30H,38H,32H     ;加数ASCII码
DATA    ENDS

STACK   SEGMENT STACK                   ;堆栈段
STA     DB      20 DUP(?)
TOP     EQU     LENGTH STA
STACK   ENDS

CODE    SEGMENT
        ASSUME  CS:CODE,DS:DATA,SS:STACK,ES:DATA
START:  MOV     AX,DATA
        MOV     DS,AX
        MOV     AX,STACK
        MOV     SS,AX
        MOV     AX,TOP
        MOV     SP,AX
        MOV     SI,OFFSET DATA2         ;SI存放数据地址
        MOV     BX,05                   ;BX中存放数字长度
        CALL    DISPL                   ;显示加数
        CRLF
        MOV     SI,OFFSET DATA1         ;源地址指向被加数
        MOV     BX,05
        CALL    DISPL                   ;显示被加数
        CRLF
        MOV     DI,OFFSET DATA2         ;目的地址指向加数
        CALL    ADDA                    ;调加法运算子程序
        MOV     SI,OFFSET DATA1
        MOV     BX,05
        CALL    DISPL                   ;显示结果
        CRLF
        MOV     AX,4C00H
        INT     21H                     ;返回DOS

DISPL   PROC    NEAR                    ;显示子程序
DS1:    MOV     AH,02
        MOV     DL,[SI+BX-1]            ;显示字符串中一个字符
        INT     21H
        DEC     BX
        JNZ     DS1
        RET
DISPL   ENDP

ADDA    PROC    NEAR                    ;加法运算子程序
        MOV     DX,SI
        MOV     BP,DI
        MOV     BX,05
AD1:    SUB     BYTE PTR [SI+BX-1],30H  ;将ASCII码转换位二进制数
        SUB     BYTE PTR [DI+BX-1],30H
        DEC     BX
        JNZ     AD1
        MOV     SI,DX
        MOV     DI,BP
        MOV     CX,05                   ;五位数加法, 5 作为循环次数
        CLC                             ;清进位标志
AD2:    MOV     AL,[SI]
        MOV     BL,[DI]
        ADC     AL,BL                   ;带进位加法
        AAA                             ;非组合BCD码调整
        ;如果al的低4位是在0到9之间,保留低4位,清除高4位,如果al的低4位在10到15之间
        ;则通过加6,来使得低4位在0到9之间,然后再对高4位清零。
        ;如果al的低4位是在0到9之间,ah值不变,CF和AF标志清零,否则,ah=ah+1,并设置CF和AF标志
        MOV     [SI],AL                 ;结果存被加数区
        INC     SI                      ;指向下一位
        INC     DI
        LOOP    AD2                     ;没有加够 5 位转
        MOV     SI,DX                   ;恢复加数,被加数地址指针
        MOV     DI,BP
        MOV     BX,05
AD3:    ADD     BYTE PTR [SI+BX-1],30H  ;转换为ASCII码
        ADD     BYTE PTR [DI+BX-1],30H
        DEC     BX
        JNZ     AD3
        RET
ADDA    ENDP
CODE    ENDS
        END     START

四、实验过程

1.用编辑器建立源文件D101-2.ASM
在这里插入图片描述
2.用汇编程序MASM.EXE对源文件进行汇编,产生目标文件,再用连接程序LINK产生可执行文件
在这里插入图片描述
3.使用调试工具DEBUG进行程序调试
先用U命令反汇编,以便了解指令地址。显示结果如下,具体调试结果见第五部分。
在这里插入图片描述

五、实验结果分析

1.程序调试及结果
可以看到在076D:0015地址处的指令是调用显示子程序DISPL来显示加数,被加数的显示类似,使用G命令执行到076D:0039处,查看显示结果。
在这里插入图片描述
使用-G 0076命令执行到ADDA子程序中,使用D命令查看ASCII码被转化为十六进制数后在内存中的存放情况,如下
在这里插入图片描述
使用-G 008f命令执行到BCD加法结束,查看被加数内存区域数值如下,因为28056+47193=75249,因此内存区域由低地址到高地址应依次为09 04 02 05 07,使用-d ds:0命令进行查看,与理论值一致。
在这里插入图片描述
继续使用G命令运行程序,直到将计算结果转化为ASCII码后,结果为
在这里插入图片描述
最后,运行到程序结束,将结果打印到屏幕上,如下:
在这里插入图片描述
2.分析总结

首先,在MASM编译器Microsoft ® Macro Assembler Version 5.00版本下,纠正实验指导书中出现的一个小问题。实验指导书中对“CRLF”命令宏的建立代码放在了文件最开头,然而在该版本编译器下编译会报错:Out of memory,将该宏命令放入代码段后编译即可编译成功,后续又将其放在文件开头编译,又可以编译成功没任何报错信息,对此迷惑不解,具体原因还需查阅相关资料。

本次实验的核心在于数据的传送指令、算数指令和循环指令的用法,其中比较重要的指令有:AAA(ASCII adjust after addition)指令,是BCD指令集中的一个指令,用于在两个未打包的BCD值相加后,调整al和ah寄存器的内容;BCD(Binary-coded decimal)数是指2进制编码的10进制数,占据一个字节的低4位,只有0-9是有效值。AAA指令做两件事情:(1)如果al的低4位是在0到9之间,保留低4位,清除高4位,如果al的低4位在10到15之间,则通过加6,来使得低4位在0到9之间,然后再对高4位清零。(2)如果al的低4位是在0到9之间,ah值不变,CF和AF标志清零,否则,ah=ah+1,并设置CF和AF标志。此外,还要搞清楚ADC等带进位加法指令与不带进位加法ADD指令的区别,将这些搞明白,则本实验的核心内容就没有什么问题了。


版权声明:本文为wlwdecs_dn原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。