北邮微原软件实验四:子程序设计
一.实验目的:
1.进一步掌握子程序设计方法;
2.进一步掌握基本的 DOS 功能调用.
二.实验内容:
1.从键盘上输入某班学生的某科目成绩.输入按学生的学号由小到大的顺序输入.
2.统计检查每个学生的名次.
3.将统计结果在屏幕上显示.
4.为便于观察,输入学生数目不宜太多,以不超过一屏为宜.输出应便于阅读.尽可能考虑美观.
5.输入要有检错手段.
Contents
仙剑95进度汇报
没见过这么强大的对手~幸好存档了。打了两回才干掉他们。
编程思路
之前两个实验已经把各个模块做好了。现在只需要把前面的模块拼凑起来,加上排名功能即可。
排名:这里用的方法是把每个学生的成绩跟其他学生比较,算法复杂度极高。考虑到实验要求的人数不多,可采取此方法来减少代码量。
源代码
;---------------------------------- ;Exercise 3. ;input scores in order. ; ; ;1. Ask for user input.(With checking) ;2. Check end_flag. ;3. Not end: append data. ;4. End input: Calculate ranking. ;5. Output assume cs:codesg,ds:datasg,ss:stacksg Stacksg SEGMENT STACK 'STACK' DB 100H DUP(0) Stacksg ENDS datasg segment n_student db 00h ranking db 100H DUP(1) scores db 200H DUP(0) ; the score of each student is represent as 9,9 for 99. current_num db 0,0 end_flag db 0 illegal_num_msg db 'ooooops,something wrong with your input. $' title_string db 'ID',9,'SCORE',9,'RANKING','$' datasg ends codesg segment main proc initialize: sub ax,ax mov ax,datasg mov ds,ax get_input: call get_2digits_input cmp end_flag,1 jz end_input mov bl,n_student rol bl,1 mov bh,00H mov al,current_num[0] mov scores[bx],al mov al,current_num[1] mov scores[bx+1],al inc n_student jmp get_input end_input: sub cx,cx sub dx,dx mov si,0 mov di,0 mov cl,n_student mov ch,0 loop1: push cx sub bx,bx ; bx = the n of student that going to compare. mov dh,scores[si] ; Score[0] of current student. mov dl,scores[si+1] ; Score[1] of current student. mov cl,n_student mov ch,0 loop2: compare10: cmp dh,scores[bx] jb inc_rank cmp dh,scores[bx] jz compare1 jmp next_cmp_student compare1: cmp dl,scores[bx+1] jb inc_rank jmp next_cmp_student inc_rank: inc ranking[di] next_cmp_student: inc bx inc bx loop loop2 inc si inc si inc di pop cx loop loop1 output: call print_nl lea dx,title_string call print_string call print_nl mov cl,n_student mov ch,0 mov si,0 ; keep track of student id. mov bx,0 ; keep track of score position. out_loop: mov ax,si call print_num mov al,9 call print_char mov al,9 call print_char mov al,9 call print_char mov al,9 call print_char mov al,scores[bx] call print_num mov al,scores[bx+1] call print_num mov al,9 call print_char mov al,9 call print_char mov al,9 call print_char mov al,9 call print_char mov al,ranking[si] call print_num call print_nl inc si inc bx inc bx loop out_loop exit: mov ax,4c00H int 21H main endp ;-------------------------------------------- ; Process: get_2digits_input ; This process would get a 2-digit-decimal number input from DOS. ; This process requires 2 global variables: end_flag, current_num[2]. ; Input: null ; Output: a number(range 0-99 decimal) in current_num[2](global variable). If encounter a end_symbol, set end_flag to 1. ; 1. Initialize variables, set end_flag and current_num to 0. ; 2. Push registers into stack. ; 3. Get a char input. (input10) ; 4. Check if it is separate_symbol or end_symbol. If it is, end this process. (check_s,check_e) ; 5. Check if the input is legal(range '0' to '9'),and transform to number from ASCII. (check_legal) ; 6. Get another char input.(input1) ; 7. Check if it is separate_symbol or end_symbol. If it is, end this process. ,and check if the input is legal.(range '0' to '9') ; 8. If input legal,add to current_num directly. (add one) ; 9. Pop registers,return. (return) end_symbol EQU 'e' separate_symbol EQU ' ' get_2digits_input proc mov end_flag,0 mov current_num[0],0 mov current_num[1],0 push ax push bx push cx push dx input10: mov ah,01 int 21h check_s: cmp al,separate_symbol jnz check_e jmp return check_e: cmp al,end_symbol jnz check_legal mov end_flag,1 jmp return check_legal: call check_num add_tens: mov current_num[0],al input1: mov ah,01 int 21h check_s1: cmp al,separate_symbol jnz check_e1 jmp return check_e1: cmp al,end_symbol jnz check_legal1 mov end_flag,1 jmp return check_legal1: call check_num add_ones: mov current_num[1],al jmp input10 return: pop dx pop cx pop bx pop ax ;-----Debug------ ;call print_nl ;mov al,current_num[0] ;call print_num ;mov al,current_num[1] ;call print_num ;---------------- ret get_2digits_input endp ;-------------------------------------------- ; Process: check_num ; This is a sub-process of get_2digits_input ; input: al (ASCII) ; output: al (unsigned integer) check_num proc cmp al,'0'-1H jna illegal_num cmp al,'9'+1H jnb illegal_num sub al,'0'-0H ret illegal_num: push dx call print_nl lea dx,illegal_num_msg call print_string call print_nl mov al,0 pop dx ret check_num endp ;--------------------------- ;Process: print_num ;input: al = number ;output: a number char on screen. print_num proc push dx add al,'0'-0h mov ah,02h mov dl,al int 21h pop dx ret print_num endp ;--------------------------- ;Process: print_string ;input: DS:DX, set DS:DX to string address,and call this process. The string should end with '$' ;output: Screen. print_string proc mov ah,09h int 21h ret print_string endp ;--------------------------- ;Process: Print_nl ;input: Null. ;output: a newline on screen print_nl proc push dx mov ah,02h mov dl,0dh int 21h mov dl,0ah int 21h pop dx ret print_nl endp ;--------------------- ; Process: print_char ;input: DL,the ASCII of the char. ;output: a char on screen print_char proc mov ah,02h int 21h ret print_char endp codesg ends end main
问题分析
程序有一个严重的bug,这个bug出现在“数字显示”模块。当人数超过9个人的时候,排名显示出来的数字就会变成字母。因为这个数字显示模块只支持一位数字。