微机原理软件实验报告.docx_第1页
微机原理软件实验报告.docx_第2页
微机原理软件实验报告.docx_第3页
微机原理软件实验报告.docx_第4页
微机原理软件实验报告.docx_第5页
已阅读5页,还剩48页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

信息与通信工程学院微机原理软件实验报告班级: 2008211113 姓名: 学号: 日期: 2010年12月实验一 DEBUG 的使用1一、实验目的1二、实验内容1三、预习思考3四、实验过程4五、实验总结7实验二 分支、循环程序设计8一、实验目的8二、实验内容8三、预习思考8四、实验过程9(一)、流程图9(二)、源代码10(三)、实验分析13五、实验总结14实验三 代码转换程序设计15一、实验目的15二、实验内容15三、预习思考15四、实验过程16(一)流程图16(二)模块层次图16(三)源代码17(四)实验分析21五、实验总结22实验四 子程序设计23一、实验目的23二、实验内容23三、预习思考23四、实验过程24(一)流程图24(二)模块层次图25(三)源代码25(四)实验分析39五、实验总结40实验五 中断程序设计41一、实验目的41二、实验内容41三、预习思考41四、实验过程42(一)流程图42(二)源代码43(三)实验分析49五、实验总结50实验一 DEBUG 的使用一、实验目的1. 掌握汇编程序的编辑、编译、连接和执行的全过程;2. 学习和掌握用DEBUG调试程序的方法。二、实验内容1. 用编辑软件,输入以下汇编语言源程序: DAT SEGMENT A DB 20 B DB 15 Y DB 3 DUP(0) Z DB 0,0 DAT ENDS STA SEGMENT STACK DW 50 DUP(?) STA ENDS COD SEGMENT ASSUME CS:COD,DS:DAT STAR PROC FAR PUSH DS XOR AX,AX PUSH AX MOV AX,DAT MOV DS,AX MOV AX,STA MOV SS,AX MOV AL,A MOV Z,AL MOV Z+1,AL CALL SUB1 MOV AL,B MOV Z,AL MOV Z+1,AL CALL SUB1 MOV AL,A MOV Z,AL MOV AL,B MOV Z+1,AL CALL SUB1 ADD WORD PTR Y,AX ADC BYTE PTRY+2,0 RET STAR ENDP SUB1 PROC MOV AL,Z MOV AH,Z+1 MUL AH ADD WORD PTR Y,AX ADC BYTE PTRY+2,0 RET SUB1 ENDP COD ENDS END STAR2. 通过编译,连接形成可执行文件。3. 用 DEBUG 将可执行文件调入,并进行调试。1) 用 D 命令观察数据区在内存中的具体内容,记录单元 A 和 B 的具体地址。2) 用 U 命令对目标代码反汇编,观察反汇编后的结果。注意发现源程序的起始位置,并记录这个起始地址。3) 用 T 命令作单步跟踪调试。比较每条指令执行后的结果和原来的理解是否 一致,得出程序运行的结果:它们是写在什么单元,具体内容是什么;并判断结果是否正确。在子程序 SUB1 的入口处设一断点,用 G 命令执行程序。 在断点处观察堆栈的内容,比较堆栈的内容和程序返回地址是否一致。4) 用 E 命令修改单元 A,B 的内容,重新执行程序,并记录结果。5) 用 M 命令和 A 命令对程序进行修改:将主程序中最后两条指令 (ADD 和ADC) 修改为一条 CALL SUB1 指令,重新执行程序。6) 退出 DEBUG。4. 重新使用编辑软件,把源程序最后一句中的 STAR 去掉。再次生成可执行文件,并用 DEBUG 调入内存。当使用 U 命令时,显示的结果与前一次(未加 STAR) 的结果有何不同?三、预习思考1. 熟悉常用的 DEBUG 命令。答:常用的DEBUG命令如下图表所示。2. 阅读并分析程序的功能。答:程序完成的功能是计算两个数的完全平方和,即计算。3. 若 SS=2000H,SP=FFFFH, 向堆栈中压入 4 字节数据后,如何用 D 命令显示压入堆栈的内?答:使用的命令是:-D 2000:FFFB,即使用段基址加偏移量查看。四、实验过程以下由实验截图展现具体的实验过程,截图进行了详细标注,便于阅读。上图为编译、链接形成可执行文件的过程。上图展现了进行反编译然后使用D命令查看数据段中A、B值的过程。上图使用E命令对数据段数据A和B进行了修改,分别由20和15改为了48和64,修改后用D命令进行了查看。上图演示了如何设置断点。在SUB1出设置一断点,可以看到程序执行到CALL 0003F时中断,各寄存器的值均有显示。下图为调用子程序SUB1,然后子程序结束,返回主程序前寄存器的值。可以看到,压入堆栈的IP值弹出,CS:IP已经指向了下一条语句的地址。下图中操作实现的功能是将ADD和ADC两条语句替换为CALL语句,通过A命令可以直接修改程序指令,通过插入NOP指令使CPU空闲。也可以通过M命令拷贝CALL SUB1的机器代码到目的地址,但操作容易出错,原因是源地址和目标地址指令长度不一致。当重新使用编辑软件,把源程序最后一句中的 STAR 去掉。再次生成可执行文件,再次DEBUG时。当使用 U 命令时,结果如下图所示。可以看到,没有END STAR语句,编译器将不知道代码段的入口地址是多少,导致从数据段开始译码,后续译码全部紊乱。END STAR的作用是指示编译器程序结束,同时告诉编译器程序执行时代码段的入口地址。五、实验总结此次实验是微机原理软件实验的第一次实验。由于平时只是注重理论的学习,没有多少实际编程和调试经验,上机操作还不熟练。以后需要加强实践。汇编的调试很重要,有时比写出源代码更重要。代码是很容易写出的,就看是好是坏,编程技巧是否足够,编程经验是否丰富,但代码的测试,排错确实十分困难的,很难把每一种可能的情况考虑周到,用户的操作也可能出现各种不可预知的情况,往往细小的错误甚至是不明确的地方都可能成为错误的隐患。这也就是为何软件开发三个之一的人写代码,三分之二的人进行测试。这次实验我学会了汇编程序的基本调测方法,也体会到汇编的调试和C/C+或者Java调试的差异。汇编的调试需要深入堆栈和内存区,关心每一地址和每一个指令。这也体现汇编是底层语言的特点。实验二 分支、循环程序设计一、实验目的1. 开始独立进行汇编语言程序设计;2. 掌握基本分支,循环程序设计;3. 掌握最简单的 DOS 功能调用。二、实验内容1. 安排一个数据区,内存有若干个正数,负数和零。每类数的个数都不超过 9。2. 编写一个程序统计数据区中正数,负数和零的个数。3. 将统计结果在屏幕上显示。4. (扩展题)统计出正奇数、正偶数,负奇数、负偶数以及零的个数。三、预习思考1. 十进制数 0 9 所对应的 ASCII 码是什么? 如何将十进制数 0 9 在屏幕上显示出来?答:09分别对应ASCII码的30H39H。欲将十进制数09显示在屏幕上,只需要用二进制数09分别加上30H即可。2. 如何检验一个数为正,为负或为零? 你能举出多少种不同的方法?答:方法有多种,现举出两种。一是直接用CMP命令和0比较,然后用JZ等命令进行判断;二是和0相比是否相等,然后用该数(假设为8位)和10000000相与,取出符号位判断,可区分正负。其余方法大同小异,核心的思想是要么直接和0相比,要么使用逻辑或移位运算,取出符号为进行判断。四、实验过程(一)、流程图(二)、源代码DATA SEGMENT ARRAY DB 1,2,3,4,5,6,-1,-2,-3,0,0,0 LENG EQU $-ARRAY; 数组长度 POSI DB ?; 正数个数 NEGT DB ?; 负数个数 ZERO DB ?; 零的个数 POSIEVEN DB ?;正偶数 POSIODD DB ?; 正奇数 NEGTEVEN DB ?; 负偶数 NEGTODD DB ?; 负奇数 ;用于打印提示的字符串定义 POSICHAR DB Positive: $ NEGTCHAR DB Negtive: $ ZEROCHAR DB Zero: $ EVENCHAR DB Even: $ ODDCHAR DB Odd: $ CR DB 0DH,0AH,$; 回车换行的ASCII码DATA ENDS;-CODE SEGMENT ASSUME CS:CODE,DS:DATA;-START: MOV AX,DATA MOV DS,AX MOV SI,OFFSET ARRAY-1 MOV CL,LENG; 数组长度赋予CL MOV AL,0LOP: CMP CL,0; 循环控制条件:数组长度减为零 JE CALC; 为零则跳出 INC SI DEC CL MOV BL,SI;采用基址加变址寻址 CMP BL,AL; 和零比较 JG ISPOSI; 是正数跳转 JE ISZERO; 是零跳转 JL ISNEGT; 是负数跳转;-ISPOSI: INC POSI; 正数个数加一 AND BX,1 ADD POSIEVEN,BL; 和1与之后的结果加到正偶数中 JMP LOPISZERO: INC ZERO JMP LOPISNEGT: INC NEGT; 负数个数加一 AND BX,1ADD NEGTEVEN,BL; 和1与之后结果加到负偶数中 JMP LOP ;-CALC: MOV AH,POSI MOV AL,POSIEVEN SUB AH,AL; 计算正奇数个数 MOV POSIODD,AH MOV AH,NEGT MOV AL,NEGTEVEN SUB AH,AL; 计算负奇数个数 MOV NEGTODD,AH;-PRINT: ;打印正数提示符和正数(奇偶)个数 MOV AH,09H MOV DX,OFFSET POSICHAR INT 21H MOV AH,02H MOV DL,POSI ADD DL,30H INT 21H MOV AH,09H MOV DX,OFFSET EVENCHAR INT 21H MOV AH,02H MOV DL,POSIEVEN ADD DL,30H INT 21H MOV AH,09H MOV DX,OFFSET ODDCHAR INT 21H MOV AH,02H MOV DL,POSIODD ADD DL,30H INT 21H MOV DX,OFFSET CRMOV AH,09H INT 21H;- ;打印负数提示符和负数(奇偶)个数 MOV AH,09H MOV DX,OFFSET NEGTCHAR INT 21H MOV AH,02H MOV DL,NEGT ADD DL,30H INT 21H MOV AH,09H MOV DX,OFFSET EVENCHAR INT 21H MOV AH,02H MOV DL,NEGTEVEN ADD DL,30H INT 21H MOV AH,09H MOV DX,OFFSET ODDCHAR INT 21H MOV AH,02H MOV DL,NEGTODD ADD DL,30H INT 21H MOV DX,OFFSET CR MOV AH,09H INT 21H MOV AH,09H MOV DX,OFFSET ZEROCHAR INT 21H MOV AH,02H MOV DL,ZERO ADD DL,30H INT 21HEXT: MOV AX,4C00H INT 21H;-CODE ENDS END START(三)、实验分析数据区待统计的数据为:1 , 2 , 3 , 4 , 5 , 6 , -1 , -2 , -3 , 0 , 0 , 0 实验结果如下图所示。本实验较为简单,意在练习基本的分支、循环结构。关键的点在于和0比较,区分正负和零,然后在正数和负数中判断奇偶,这里巧妙地使用了和1与之后加和到偶数中,最后利用统计的数的个数减去偶数得奇数的方法。使得程序更加流畅和简洁,思路也更清晰。五、实验总结实验中设计好的计算思路是很重要的,汇编的代码由各种跳转和逻辑结构组成,需要考虑代码间的逻辑关系,否则容易出错。语法错误是很显而易见的,但逻辑错误却不容易发现。当有大量判断和循环存在时,需要考虑清楚程序跳转的条件和方向,这点和高级语言有较大差异,汇编本质上没有循环和分支,都是通过将IP赋予代码区地址进行跳转实现的,程序员需要自主控制如何跳转,向何处跳转,这点和C/C+中饱受诟病的goto语句处理有些类似。考虑到实验练习的重点在分支循环结构,此次写代码时暂时没有使用子程序或宏,导致输出部分代码有些过长。实验三 代码转换程序设计一、实验目的1. 掌握几种最基本的代码转换方法;2. 运用子程序进行程序设计。二、实验内容1. 从键盘上输入若干两位十进制数,寻找其中的最小值,然后在屏幕上显示出来。2. 两个十进制数之间的分隔符,输入结束标志自定,但要在报告中说明。3. 对输入要有检错措施,以防止非法字符输入,并有适当的提示。4. 将整个程序分解为若干模块,分别用子程序实现。在报告中要给出模块层次图。三、预习思考1. 如何将输入的两个字符(09)变为十进制或二进制数?答:输入的字符09是ASCII码表示的,对应于30H39H,通过减去30H,可以转换为相应的计算机数。2. 如何将选出的最小值(二进制或十进制)变为 ASCII 码再进行显示?答:如果采用输入时把ASCII码转换为数字,然后比较数字的大小再输出,那么输出时还需要把数字再次转换为ASCII码。这是不明智的。可以直接读入并存储数字的ASCII码,容易比较其大小,然后直接输出ASCII码即可。3. 你觉得采用二进制运算还是十进制运算更适合于这个实验?答:采用二进制或者十进制都需要进行ASCII码到数字的转换和其反向转换,换用新的思路可以大大简化编程负担。即直接使用数字对应的ASCII比较,分别比较十位和个位,最后直接输出字符即可。四、实验过程(一)流程图(二)模块层次图(三)源代码DATA SEGMENTINPUT DB 100 DUP(?)MINTMP DB 9-30H,9-30H ; 置最小值的初始值为99COUNT DB 0DIFERROR DB 0D; 用于判断调用输入子程序是否有错;提示信息字符串WELCOME DB Please input numbers:,$OUTTIP DB Minimum is :,$CR DB 0DH,0AH,$; 回车换行;各种错误输入提示 ERROR1 DB ERROR:Character is not valid!,$ ERROR2 DB ERROR:Number must contains two digits!,$ ERROR3 DB ERROR:Number is empty!,$ ERROR4 DB ERROR:Need separate char!,$DATA ENDS;-CODE SEGMENT ASSUME CS:CODE,DS:DATAMAIN PROC FAR MOV AX,DATA MOV DS,AX MOV DX,OFFSET WELCOME; 调用欢迎提示 CALL PRINT MOV DX,OFFSET CR; 回车换行 CALL PRINT CALL GETNUM; 获取用户输入 CMP IFERROR,0; 判断输入过程是否有错 JNZ BACK; 错误则直接返回DOS MOV DX,OFFSET CR; 回车换行 CALL PRINT CALL FINDMIN; 查找最小数 MOV DX,OFFSET OUTTIP; 调用输出提示 CALL PRINT MOV AH,02H MOV DL,MINTMP; 输出最小值的十位 ADD DL,30H INT 21H MOV AH,02H MOV DL,MINTMP1; 输出最小值的个位 ADD DL,30H INT 21H BACK: MOV AX,4C00H; 返回DOS INT 21HMAIN ENDP;-;获取输入,出口参数为IFERROR,表示是否有错GETNUM PROC PUSH AX; 保存现场 PUSH BX PUSH CX PUSH DX PUSH DI MOV DI,0; 数组偏移地址 MOV CX,0; 标识数字的位数GETLOOP: MOV AH,01H; 从键盘读取一个字符 INT 21H CMP AL,0DH; 和回车比较 JE EXIT1; 是回车则结束输入 CMP CX,0; 数字位数为空 JE CMPSPACE0 CMP CX,1; 数字位数为1 JE CMPSPACE1 CMP CX,2; 数字位数为2 JE CMPSPACE2CMPSPACE0: CMP AL,20H JE GETLOOP; 数字位数为0且输入空格则忽略,继续输入 JMP ASCBIN; 不是空格就读取该字符CMPSPACE1: CMP AL,20H JE ERR2; 数字位数为1且输入空格则位数不是两位数出错 JMP ASCBIN; 否则读取该字符CMPSPACE2: CMP AL,20H JNE ERR4; 数字位数为2后,不输入空格则分隔符错误 XOR CX,CX; 输入空格则清零重新计数 JMP GETLOOP ASCBIN: SUB AL,30H; 化为二进制数字 JL ERR1; 小于则无效字符 CMP AL,9; 和9比较 JG ERR1; 大于9则是无效字符 MOV INPUTDI,AL; 保存输入的数 INC COUNT; 统计输入的数字个数,为判断是否输入为两位数 INC DI; 向后移动数组 INC CX JMP GETLOOPERR1: MOV IFERROR,1; 输出错误1 MOV DX,OFFSET ERROR1 CALL PRINT JMP RETURNERR2: MOV IFERROR,1; 输出错误2 MOV DX,OFFSET ERROR2 CALL PRINT JMP RETURN ERR3: MOV IFERROR,1; 输出错误3 MOV DX,OFFSET ERROR3 CALL PRINT JMP RETURN ERR4: MOV IFERROR,1; 输出错误4 MOV DX,OFFSET ERROR4 CALL PRINT JMP RETURN EXIT1: MOV BL,COUNT; 判断输入数的个数是否为零 CMP BL,0 JE ERR3;输入数目为0则输出错误并退出 AND BL,01H; 判断数字是否为两位数 CMP BL,0 JNE ERR2;输入数字个数为奇数则出错RETURN: POP DI; 恢复现场 POP DX POP CX POP BX POP AX RETGETNUM ENDP;-;回车换行输出字符串,入口参数为DXPRINT PROC PUSH AX MOV AH,09H INT 21H POP AX RETPRINT ENDP;-;查找最小的数子程序FINDMIN PROC PUSH DI; 保护现场 PUSH AX PUSH CX MOV DI,-2; 数组下标 MOV CL,COUNT; 把数组长度移入CX MOV AL,CL CBW MOV CX,AXLOP: ADD DI,2 CMP CX,DI; 是否已经比较完毕 JE EXIT2; 如果比较完毕所有数则退出 MOV AH,INPUTDI;否则接着比较,移入十位数 MOV AL,INPUTDI+1; 移入个位数 CMP AH,MINTMP; 比较十位数,MINTMP低地址为十位 JA LOP ;如果MINTMP小,则直接比较下一个数 JE HIGHEQU ;如果十位数相等,比较个位数,再否则十位大就直接存储STOMIN: MOV MINTMP,AH MOV MINTMP1,AL JMP LOPHIGHEQU: CMP AL,MINTMP1; 比较个位数 JNB LOP; 个位数比MINTMP大则跳到下一个数 JMP STOMIN; 否则将当前数写入为MINTMPEXIT2: POP CX POP AX POP DI RETFINDMIN ENDP;-CODE ENDS END MAIN(四)实验分析下图是实验输出结果截图。实验中以空格为分隔符,空格的个数不限制,以回车为输入结束标志符。对输入的数字进行了位数和范围的严格限制,即必须是两位数字,如果数字小于10,需要补齐零。实验中对输入错误执行严格的检查,出错则重新输入。判断输入错误的核心思路为:以空格为分割,以回车结束,要求必须是两位数,也即,一位数字后不能有空格,两位数字后必须有空格,回车之后总的输入进行判断,数字个数必须为偶数,以上三种情况囊括了所有可能的格式错误,不满足任何一个条件即出错。满足格式输入后,再判断字符的是否09,不是则出错。每项错误均已错误列表的形式给出,打印出错误提示。总结实验中的关键设计思路如下:1、严格的输入格式检查,严格的输入字符有效性检查。2、以数组方式进行存储,每两个BYTE存储一个输入的两位数,存储格式为字符ASCII码。不进行字符ASCII码到数字的转换。3、比较数字大小时,采用分别比较高位ASCII码和低位ASCII码的方式,从而不用在输入时将字符存储为数字,输出时也不用再进行逆转换。程序效率大为提高。4、为使得程序结构清晰,减小代码耦合度,采用了多子程序的设计方式。把实验任务分为三步:读取输入、找出最小、输出打印,分别以子程序方式实现,主调函数依次调用完成实验任务。五、实验总结本实验的关键点在于如何设计子程序完成部分功能。在设计子程序的过程中,我依据结构化代码的流程进行划分,自然形成了读取输入、找出最小、打印输出的思路。这一思路是没有问题的,但存在子程序划分还不够细致的问题,比如,读取输入子程序代码过于冗长,这是因为我没有把输入格式检查、错误提示单独作为子过程进行独立编写。这是设计中的一大不足,这一缺陷也让我在调试子程序的时候颇费周折。这次教训一定要铭记。实验中比较大小的方式有多种,如何采用更加简洁有效的方式是值得思考的问题。我一开始也不免陷入到比较数字大小的常规方法中,但由于汇编输入具有特殊性,即输入的是ASCII码而非数字的大小,且存在将两个字符进行连接成为两位数的需求,而输出时又需要进行反过程。考虑到ASCII也是可以比较的,且十位数和个位数是可以分别比较的这一情况,我采用了巧妙的方式进行处理。这说明,在实际的编程中,需要根据具体情况调整一般方法,使得方法更加简洁可行且有效。实验四 子程序设计一、实验目的1. 进一步掌握子程序设计方法;2. 进一步掌握基本的 DOS 功能调用。二、实验内容1. 从键盘上输入某班学生的某科目成绩。输入按学生的学号由小到大的顺序输入。2. 统计检查每个学生的名次。3. 将统计结果在屏幕上显示。4. 为便于观察,输入学生数目不宜太多,以不超过一屏为宜。输出应便于阅读.尽可能考虑美观。5. 输入要有检错手段。三、预习思考1. 如何确定一个学生在这门科目中的名次?答:有两种基本思路,一是抽取每个学生的成绩和其他所有学生的成绩进行比较,然后统计比其分数高的学生,得出该学生的名次;二是把学生成绩存入连续内存区域,即数组方式,取得每个学生的成绩偏移量,即成绩指针。然后比较指针所指的成绩的大小,根据比较结果移动指针完成排序。具体排序时可以采用诸多的方式,比如冒泡法,快速排序法等等,均是可行的。本实验采用第二种方式,用冒泡法予以具体实现。2. 输入结束后,采用什么方法进行比较以得到学生的名次最为简单?答:如上问所述,采用冒泡排序法可获得较好的时间和空间性能。冒泡法平均时间性能O(N2)。相比于直接比较,性能有所改善。但相对于快速排序、归并排序等优化的算法的时间复杂度O(N*log2N)还不够好。但后两者使用汇编实现代码的复杂度和编程要求要高。考虑到学生人数比较少,使用冒泡法是比较简洁的,时间性能是可以接受的。3. 准备好模块层次图。答:见下文“实验过程”中所示。4. 给出输出显示的形式。答:输出以列表形式给出。学号、分数、名次各一列。具体形式参见实验分析部分的输出截图。四、实验过程(一)流程图(二)模块层次图(三)源代码DATA SEGMENTID DB 400 DUP(?);存储学号,每个16固定个BYTE,存储为字符串MARK DB 20 DUP(?); 存储分数,每个1BYTE,存储为二进制数RANK DB 20 DUP(?); 存储排名,每个1BYTE,存储为二进制数RANKTMP DB 20 DUP(?); 排序时指针临时区MTMP DB ?; 记录成绩的临时区COUNTB DB ?; 记录总的学生的个数,存为8位COUNTW DW ?; 记录总的学生个数,存为16位CHEOK DB ?; 输入检查标志位ERROR DB ?; 记录错误号TMP DB 2 DUP(?); 开辟两个内存临时存储区,用作判断和计数CR DB 0DH,0AH,$; 回车换行TAB DB 09H,09H,$;输出TAB键ERR0 DB Input cannot be empty!,$ERR2 DB Character is invalid!,$ERR4 DB Mark is invalid!,$ERR6 DB Input is invalid!,$ERRLIST DW ERR0,ERR2,ERR4,ERR6TIP0 DB Please re-input:,$TIP1 DB Please input number of students:,$TIP2 DB Please input ID and MARK:,$PRTIP DB -RESULT-,$PRINFO DB ID,09H,09H,MARK,09H,09H,RANK,$PRPRE1 DB ID : ,$PRPRE2 DB MARK: ,$BUFF DB 16; 定义输入缓冲区,最长的字符长度PRES DB ?; 存储实际输入了多少个字符CHAR DB 16 DUP(?); 实际可存储有效字符16个DATA ENDSCODE SEGMENT;-;打印提示字信息的宏,形参为PARAPRINTTIP MACRO PARAPUSH AXPUSH DXMOV AH,09HMOV DX,OFFSET PARAINT 21HPOP DXPOP AXENDM;-;打印单个字符的宏,形参为ACHARPRINTCHAR MACRO ACHARPUSH AXPUSH DXMOV AH,02HMOV DL,ACHARINT 21HPOP DXPOP AXENDM;-;主程序MAIN PROC FAR ASSUME CS:CODE,DS:DATA,ES:DATA MOV AX,DATA MOV DS,AX MOV ES,AX CALL GETNUMBER; 获得学生的人数 CALL GETINFO; 获得学号分数的输入 CALL SORT; 执行排序活动名次 CALL PRINT; 把名次结果打印出来BACK:MOV AX,4C00H; 返回DOS INT 21HMAIN ENDP;-;获得将要输入的学生的人数信息的子程序;每班的学生定义不超过100人GETNUMBER PROC NEARPUSH AXPUSH BXHE:PRINTTIP TIP1GREP: CALL GETIN; 获取一个输入缓冲MOV CHEOK,0CALL CHECKCMP CHEOK,0JE GRETURNMOV ERROR,6CALL PRINTERRPRINTTIP TIP0 PRINTTIP CRJMP GREPERRHERE: PRINTTIP CRMOV ERROR,6CALL PRINTERRPRINTTIP TIP0JMP GREP GRETURN: CALL CHANGEMOV AL,MTMPCMP AL,0JE ERRHEREMOV COUNTB,AL; 写入人数CBWMOV COUNTW,AXPRINTTIP CRPOP BXPOP AXRETGETNUMBER ENDP;-;循环直到输入人数满时终止,获得输入的字符串GETINFO PROC NEARPUSH AXPUSH BXPUSH CXPUSH DXPUSH SIPUSH DIPRINTTIP TIP2MOV TMP,0; 记录是学号还是分数XOR BX,BX; 记录每个ID的偏移量XOR AX,AX; 记录学生数目MORE:PRINTTIP CRCMP COUNTB,AL JNZ HERE1 JMPRETURN; 计数器为0则返回父程序HERE1: CMP TMP,0JE PR1CMP TMP,1JE PR2PR1:PRINTTIP PRPRE1JMP HERE2PR2:PRINTTIP PRPRE2HERE2:CALL GETIN; 否则接受输入CALL CHECK; 检查输入是否是数字且不为空CMP CHEOK,0JNE CHEFAIL; 不为零则不合法,需要重新输入CMP TMP,0JE ISID ; 输入的是学号CMP TMP,1 ; JE ISMARK ;输入的是分数CHEFAIL:PRINTTIP TIP0 PRINTTIP CRMOV CHEOK,0; 重新把返回判断位置零JMP MORE;写入学号,固定为16个字符ISID:MOV DL,PRES; 抽取需要写入字符的个数XOR DH,DHMOV CX,DXMOV SI,CXINC CXMOV CHARSI,$; 把最后一个字符之后的位置填充为$;开始写入IDMOV TMP,1; 表示下一个是分数CLDMOV SI,OFFSET CHARMOV DI,OFFSET IDADD DI,BXREP MOVSB ;写入ID; 写完则为接受下一个输入BUFF作准备ADD BX,16; ID的偏移地址向后挪动固定的16BYTEJMP MORE; 跳回继续输入下一个BUFF;是学号,检查、转换、写入保存ISMARK:CALL CHANGECMP CHEOK,0JE WRITEMARKMOV ERROR,4JMP CHEFAILWRITEMARK:PUSH BXMOV BL,MTMPMOV DI,AXMOV MARKDI,BL; 实际写入成绩POP BXMOV TMP,0; 计数清理,表明下一个输入为学号INC AX; 已接受的学生个数加一JMP MORERETURN:POP DIPOP SIPOP DXPOP CXPOP BXPOP AXRETGETINFO ENDP;-;获得一次BUFF输入子程序;入口参数为BUFF的偏移地址,出口参数为BUFF中的字符串GETIN PROC NEARPUSH AXPUSH DXPUSH DIMOV DX,OFFSET BUFFMOV AH,0AHINT 21HPOP DIPOP DXPOP AXRETGETIN ENDP;-;执行输入字符是否是数字的合法性检查CHECK PROC NEARPUSH DIPUSH CXPUSH AXXOR DI,DI; 记录CHAR读取的偏移量MOV AL,PRES; 读取输入的BUFF中的字符数CBWMOV CX,AXCMP CX,0; 判断是否输入BUFF为空JE ISEMPTY; 为空则重新输入AGAIN:CMP CX,DIJE RETURNCHECKMOV AH,CHARDICMP AH,30H; JL INVALID; 小于则无效字符CMP AH,39H; JG INVALID; 大于则是无效字符INC DIJMP AGAINISEMPTY: MOV ERROR,0 ;输入为空的处理代码PRINTTIP CRCALL PRINTERRPRINTTIP CRMOV CHEOK,1JMP RETURNCHECKINVALID: MOV ERROR,2; 输入不合法的处理代码PRINTTIP CRCAL

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论