INC SI ADD BX,16 ;进行下一个学生的打印 JMP NEXPRINT PRET: POP SI ;恢复现场 POP DX POP CX POP BX POP AX RET PRINT ENDP ;-------------------------------------------------------- CODE ENDS END MAIN
六、程序运行结果
程序运行结果如下如所示:
输入输出格式:
? 首先提示输入学生人数,然后逐个提示输入每个同学学号和分数,输入完毕之后
打印出最终结果,结果输出按照表格的形式给出,三列分别为学号、分数、排名。
? 设计输入的学生个数上限是100人,分数从0—100分。
? 学号可以输入任意长度的15位数字,存储为字符串格式,每个学生固定长度。 ? 分数经过转换后存储为数字,每人占用一个BYTE;名次亦存储为数字,每人占用
一个BYTE。
检错功能:当输入包含错误的时候,系统会有提示信息,不用返回DOS,直接重新输入。
? 输入不能为空:Input cannot be empty! ? 输入的ID不合法:Character is invalid! ? 输入的分数不合法:Mark is invalid! ? 输入字符不合法:Input is invalid! 错误截图如下:
实验的设计思路:
1、在程序设计思路上,采用了多子程序模块化设计,充分利用了宏和DOS功能调用等高级汇编技巧。
2、在数据结构设计上,采用数组的方式进行存储,可直接又下标(即学生的班内序号)进行直接寻址,效率较高。
3、在进行排名比较时,利用了指针技术,即对分数的偏移量进行排序,而不移动实际的分数。模拟了高级语言中的数组和指针的技术,结构和思路完整规范。排序技术选用了冒泡排序,获得一定的性能提升。
4、对用户输入进行严格的检查,对各种可能出现的错误进行了提示和处理。使得程
序具有很好的完备性和健壮性。
七、实验总结
本次实验的综合性比较强,包含了子程序设计、DOS调用、宏汇编等等编程方法和技术。子程序的设计可以减少主程序的运行负担和代码冗余度,充分考虑了健壮性和运行效率等因素,精心设计了数据结构和算法,是可用于实际工程的代码雏形。由于完备性、健壮性、效率、界面等方方面面都考虑到,故代码长度达到了461行。这也使得调试花费了大量时间。不过由于子程序的应用,可以分块进行调试,减小了主程序代码的长度,可以帮助梳理思路。
实验中的关键是对分数进行冒泡排序,这个在之前许多实验中都有应用,故使用起来比较顺手;为了实验的完备性,加入了较多的错误检验和处理,使程序的工程应用很强;实验中也考虑到效率问题,主要体现在大量的数据排序的问题上,考虑最佳的方案使程序运行的效率最高。
实验五 中断程序设计
一、实验目的
1. 初步掌握中断程序的设计方法;
2. 初步掌握修改 DOS 系统中断,以适应实际使用的方法。
二、实验内容
1. 编写一个 32 位二进制数除以 16 位二进制数的除法程序。观察当除数为 0,或超
过相应寄存器范围时,程序执行的结果。 2. 修改零号中断服务程序,使它具有以下功能:
(1)判断除数是否为 0,当除数为 0 时,显示相应的结果;
(2)当除数不为 0 时,采用适当的方法完成商超过 16 位的二进制数的除法运算。 3. 注意必须保护原有中断服务程序的入口地址,并在程序完毕前加以恢复。
三、预习题
1. 如何保护原有中断向量表中的中断服务程序的入口地址?
将原中断向量表中的中断服务程序的下一条指令(断点地址)的段首地址及偏移量利用PUSH命令语句压入堆栈,程序执行完毕后,用POP命令语句恢复原来的中断服务的入口地址,返回到中断发生时的主程序断点处,使主程序能够从断点恢复继续执行命令。
2. 如何将你的中断服务程序入口地址置入中断向量表?
? 直接写入法:使用指令将中断服务程序入口地址的IP写入n×4的RAM位置,中
断服务程序入口的CS写入n×4+2的位置
? 利用DOS功能调用读、写中断向量表:DOS功能调用25H用来写入中断向量表,
DOS功能调用35H用来读中断向量表。
四、选作题
1. 用二进制将结果在屏幕上显示。 2. 从键盘输入二进制数。
五、流程图
开始读取用户输入的二进制数字:32位被除数和16位除数调用二进制转换子程序修改0号向量中断表循环左移被除数/除数0号中断输入=30H?是否CF=0CF=1除数为0?否是返回DOS输出二进制序列是否溢出?否扩展商的位数为32位输出商和余数恢复0号向量中断表输出二进制除法结果返回主程序断点结束 六、源代码
DATA SEGMENT dividend DD ? ;被除数32bit divisor DW ? ;除数 16bit TMP DW ? FLAG DB 0 ;是否调用了中断处理程序的标志位,即是否溢出,不为0则溢出 ERR0 DB 'Error,divisor can not be zero! ','$' ;提示除数为0的错误消息 CHAR1 DB 'Quotient: ','$' ;输出商的结果
CHAR2 DB 'Remainder: ','$' ;输出余数的结果 CHAR3 DB 'Input high 16 bits of dividend:','$' ;输入被除数的高16位 CHAR4 DB 'Input low 16 bits of dividend:','$' ;输入被除数的低16位 CHAR5 DB 'Input 16 bits of divisor:','$' ;输入16位的除数 CR DB 0DH,0AH,'$' ;回车换行 ONE DB '1','$' ZER DB '0','$' TAB DB 09H,'$' BUFF DB 17 ;输入缓冲区,可容纳包括回车在内的17个字符 CHAR DB 17 DUP(0) DATA ENDS ;-------------------------------------------------------- ;定义堆栈 STACK SEGMENT STACK 'STACK' DB 100 DUP(0) STACK ENDS ;-------------------------------------------------------- CODE SEGMENT ASSUME DS:DATA,CS:CODE,ES:CODE,SS:STACK ;打印字符串的宏 PRINT MACRO PARA PUSH AX PUSH DX MOV AH,09H MOV DX,OFFSET PARA INT 21H POP DX POP AX ENDM ;-------------------------------------------------------- ;主程序入口 MAIN: MOV AX,DATA