一、实验目的
掌握数据传送、算术指令和循环指令的用法。
二、实验内容
将两个多位十进制数相加。要求加数,被加数均以ASCII码形式存放在以DATA1和DATA2为首的5个内存单元中( 低位在前),结果存在DATA1处。
三、程序清单
CRLF MACRO ;建立宏命令,利用INT中断实现回车换行的功能,方便后续直接调用MOV DL,0DHMOV AH,02HINT 21H ;光标移到第一列MOV DL,0AHMOV AH,02HINT 21H ;光标移到下一行
ENDMDATA SEGMENT
DATA1 DB 33H,39H,31H,37H,34H ;被加数ASCII码
DATA2 DB 36H,35H,30H,38H,32H ;加数ASCII码
DATA ENDSSTACK SEGMENT STACK ;堆栈段
STA DB 20 DUP(?)
TOP EQU LENGTH STA
STACK ENDSCODE SEGMENTASSUME CS:CODE,DS:DATA,SS:STACK,ES:DATA
START: MOV AX,DATAMOV DS,AXMOV AX,STACKMOV SS,AXMOV AX,TOPMOV SP,AXMOV SI,OFFSET DATA2 ;SI存放数据地址MOV BX,05 ;BX中存放数字长度CALL DISPL ;显示加数CRLFMOV SI,OFFSET DATA1 ;源地址指向被加数MOV BX,05CALL DISPL ;显示被加数CRLFMOV DI,OFFSET DATA2 ;目的地址指向加数CALL ADDA ;调加法运算子程序MOV SI,OFFSET DATA1MOV BX,05CALL DISPL ;显示结果CRLFMOV AX,4C00HINT 21H ;返回DOSDISPL PROC NEAR ;显示子程序
DS1: MOV AH,02MOV DL,[SI+BX-1] ;显示字符串中一个字符INT 21HDEC BXJNZ DS1RET
DISPL ENDPADDA PROC NEAR ;加法运算子程序MOV DX,SIMOV BP,DIMOV BX,05
AD1: SUB BYTE PTR [SI+BX-1],30H ;将ASCII码转换位二进制数SUB BYTE PTR [DI+BX-1],30HDEC BXJNZ AD1MOV SI,DXMOV DI,BPMOV 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 DILOOP AD2 ;没有加够 5 位转MOV SI,DX ;恢复加数,被加数地址指针MOV DI,BPMOV BX,05
AD3: ADD BYTE PTR [SI+BX-1],30H ;转换为ASCII码ADD BYTE PTR [DI+BX-1],30HDEC BXJNZ AD3RET
ADDA ENDP
CODE ENDSEND 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指令的区别,将这些搞明白,则本实验的核心内容就没有什么问题了。