一、实验目的
了解移位指令的使用方法。
掌握子程序的调用方法,了解子程序的入口参数和出口参数。
二、实验内容
将键盘接收的四位十六进制数转换为二进制数,并显示在屏幕上。
三、程序清单
CRLF MACRO ;建立宏命令,利用INT中断实现回车换行的功能,方便后续直接调用MOV DL,0DHMOV AH,02HINT 21H ;光标移到第一列MOV DL,0AHMOV AH,02HINT 21H ;光标移到下一行
ENDMDATA SEGMENT
MESS DB 'INPUT HEXNUMBER: $'
ERROR DB 'INPUT ERROR!',0DH,0AH,'$'
DATA ENDSSTACK SEGMENT STACK ;栈定义
STA DB 32 DUP (?)
TOP DW ?
STACK ENDSCODE SEGMENTASSUME CS:CODE,DS:DATA,SS:STACK,ES:DATASTART: MOV AX,DATA ;寄存器和栈初始化MOV DS,AXMOV ES,AXMOV AX,STACKMOV SS,AXMOV AX,TOPMOV SP,AXMOV AH,09H ;9号功能显示字符串以’$’作为其结束标志MOV DX,OFFSET MESSINT 21H ;调用DOS第21H号中断09H号功能显示请输入的提示信息CALL GETNUM ;调键盘输入数据子程序(数据存在DX中)MOV CX,16 ;循环次数(二进制位数)MOV BX,DX
TTT: ROL BX,01 ;循环左移移位MOV DL,BLAND DL,01H ;屏蔽高 7 位ADD DL,30HMOV AH,02HINT 21H ;显示某位二进制数LOOP TTTMOV AX,4C00HINT 21HGETNUM PROC NEAR ;键盘接收子程序,数值存DX中XOR AX,AX
GGG: MOV AH,01H;输入设备(如:键盘)读入一个字符。该中断在处理过程中将一直处于等待状态直到有字符可读为止。;该输入还可被重定向,如果这样做,则无法判断文件是否已到文件尾;AH=01H,过滤掉控制字符,并回显INT 21H ;键盘接收键盘码CMP AL,0DH ;判回车键JZ PPPCMP AL,20H ;判空格键JZ PPPCMP AL,30HJB KKKSUB AL,30HCMP AL,0AH ;判 0 - 9 数字键JB GETSCMP AL,11HJB KKKSUB AL,07HCMP AL,0FH ;判 A - F 字母键JBE GETSCMP AL,2AHJB KKKCMP AL,2FH ;判 a - f 字母键JA KKKSUB AL,20H
GETS: MOV CL,04HSHL DX,CLADD DL,AL ;十六进制数存 DX 中JMP GGG
KKK: PUSH DXMOV AH,09MOV DX,OFFSET ERRORINT 21H ;显示输入错误提示信息POP DX
PPP: PUSH DXCRLFPOP DXRET
GETNUM ENDP
CODE ENDSEND START
四、实验过程
1.用编辑器建立源文件D101-3.ASM
2.用汇编程序MASM.EXE对源文件进行汇编,产生目标文件,再用连接程序LINK产生可执行文件
3.使用调试工具DEBUG进行程序调试
先用U命令反汇编,以便了解指令地址。显示结果如下,具体调试结果见第五部分。
五、实验结果分析
1.程序调试及结果
使用G命令执行到0770:0019处,寄存器和栈已经初始化完毕,查看数据区内存信息和在屏幕输出的提示信息如下
继续执行进入到键盘输入数据GETNUM子程序中,对该子程序进行测试,输入空格键,此时因为INT 21H中断从而不能单步执行,因此直接在DOSBox中运行D101-3.exe程序,按下空格键,程序直接跳转到标号PPP处,将DX压入栈,而DX中此时为MESS处地址,因此全为0。
同理,如果按下“3+空格”输出会是什么样?显而易见,最后2位应为11,如下
当然,如果输入类似‘.’‘/’等ASCII码值小于30H的字符,则会显示输入错误!
如果输入除AF、af之外的字母,显然这些字母不能够表示十六进制数,因此同样会报错!
输入正确的四个十六进制数,例如“1234H”,在GETNUM子程序返回之前断下,即使用-G 73命令,然后键入1234,则可观察到输入内容已经被存入DX寄存器中,如下
最后通过16次循环右移,从高位到低位依次取出DX中值的每一位(比特),加上30H转化为01字符后调用21H号中断的2号功能在屏幕上打印出来,例如0x1234= 0001001000110100B,如下图。
至此,整个实验完成。
2.分析总结
首先,本次实验的重点在于了解移位指令的使用方法、掌握子程序调用方法。通常来说,移位指令比较简单易懂,包括循环移位指令;而子程序的入口和出口参数一般通过寄存器来实现,入口参数就是在调用子程序之前对该寄存器进行赋值从而达到传参的目的,出口参数就是子程序最后返回前用来存放返回结果的寄存器,也比较好理解。
而我认为本次实验的核心在于DOS系统21H号中断,即字符功能调用类(Character-Oriented Function)09H号功能,输出一个字符串到标准输出设备上,如果输出操作被重定向,那么将无法判断磁盘已满;入口参数为AH=09H,DS:DX=待输出字符的地址,待显示的字符串以’$’作为其结束标志,无出口参数。此外,在GETNUM子程序中,如何判断输入的字符是回车、空格、数字09、字母af、A~F整个过程相对来说比较复杂,其中使用的判断语句和跳转语句较多,需要静下心来慢慢梳理程序执行流程。