回 帖 发 新 帖 刷新版面

主题:[讨论]菜鸟急求高手相助!!

这是一个学生成绩管理系统,现在能求总分,还能排序,谁帮将这段程序再改成还能求平均值!!!!!我改了很久就是没有头绪!!!麻烦高手帮忙。 

回复列表 (共5个回复)

沙发

Code   Segment 
   Assume  CS:Code,DS:Code 
CR           equ   000DH 
LF           equ   000AH 
KBBack       equ   0008H 
; ------------------------------------- 
; 学生成绩结构类型 
Num   equ  5 ;科目数,最多8个科目 
Name_Length  equ  20 ;姓名长度 
Score_Stud Struc ; 学生成绩 
Name_Stud  db  Name_Length dup(?) ;姓名 
Score  db  Num dup(?) ;Num科成绩 
Sum_Score  dw  ? ;总成绩 
Score_Stud EndS 
; ------------------------------------- 
; 功能:显示指定地址(Str_Addr)的字符串 
; 入口: 
; Str_Addr=字符串地址(要求在数据段) 
; 用法: Output Str_Addr 
; 用法举例:Output PromptStr 
Output  MACRO Str_Addr 
   lea  dx,Str_Addr 
   mov  ah,9 
   int  21h 
   EndM 
; ------------------------------------- 
; 功能:在当前光标位置显示一个字符 
; 入口:dl=要显示的字符  
Output_Chr  proc  Near  
   push  ax  
   mov   ah,02h  
   int   21h  
   pop   ax  
   ret  
Output_Chr  Endp  
; ------------------------------------- 
; 功能:显示、输出一个回车、换行 
Output_CTLF proc  Near 
   push  ax  
   push  dx 
   mov   ah,02h 
   mov   dl,0dh  
   int   21h 
   mov   dl,0ah 
   int   21h  
   pop   dx 
   pop   ax 
   ret 
Output_CTLF Endp  
; ------------------------------------- 
; 功能:取光标位置 
; 入口:无 
; 出口:DH=行号,DL=列号 
GetCursor  Proc  Near 
           PUSH  DS 
           PUSH  AX 
           PUSH  BX 
           PUSH  CX 
           PUSH  DX 
           PUSH  CS 
           POP  DS 
           XOR   BX,BX 
           MOV   AH,3 
           INT   10H 
           MOV  Cursor_Row,DH 
           MOV  Cursor_Col,DL 
           POP  DX 
           POP  CX 
           POP   BX 
           POP   AX 
           POP  DS 
           RET 
Cursor_Row DB  ? 
Cursor_Col DB  ? 
GetCursor  EndP 
; ------------------------------------- 
; 功能:置光标位置 
; 入口:Cursor_Row=行坐标; Cursor_Col: 列坐标) 
SetCursor   Proc  Near 
           PUSH  DS 
           PUSH  DX 
           PUSH  CX 
           PUSH  BX 
           PUSH  AX 
           PUSH  CS 
           POP  DS 
           MOV   DH,Cursor_Row 
           MOV   DL,Cursor_Col 
           XOR   BX,BX 
           MOV   AH,2 
           INT   10H 
           POP   AX 
           POP   BX 
           POP  CX 
           POP  DX 
           POP  DS 
           RET 
SetCursor  EndP 

板凳


; ------------------------------------- 
; 功能:键盘输入一个指定位数(N)的十进制数字,将其转换成二进制数并保存在指定的内存单元。 
;       输足N位的,自动结束输入;不足N位的,空格结束输入。 
; 由于限定最大数据类型为字,所以,数字位数最多:5,最大无符号数:65536 
; 约定:直接回车,视为数字0 
; 入口:cs:@@Digits=数字位数;es:di=保存输入的数字首地址 
;       cs:@@Type_Data=保存的数据类型,B=字节类型,W=字类型。 
; 出口:转换后的二进制数保存在di所指的单元 
Input_Dec  Proc  Near 
   push  ds 
   push  dx 
   push  cx 
   push  bx 
   push  di 
   push  cs 
   pop  ds 
   call  GetCursor ;取光标位置 
   mov  dx,WORD PTR Cursor_Row 
   mov  @@Tmp_Cursor,dx ;保存起始光标位置 
   lea  di,@@Save_Tmp 
   push  di 
   cld 
   mov  cl,@@Digits 
   xor  ch,ch 
   push  cx 
@@Input_Dec: call  GetCursor ;取光标位置 
   mov  ah,1 ;从键盘接受一个字符 
   int  21h 
   cmp  al,CR ;若键入的是回车,已经键入的数字不足N位 
   jz  @@ASC_Dec ;转去处理已经键入的数字 
   cmp  al,KBBack 
   jz  @@KB_Back ;若是回空键,重新输入 
   cmp  al,'0' 
   jb  @@KBBack ;若低于数字'0',重新输入 
   cmp  al,'9' 
   ja  @@KBBack ;若高于数字'9',重新输入 
   jmp  @@Save_Dig 
@@KB_Back: cmp  cl,cs:@@Digits ;十进制数字位数 
   jz  @@Input_Dec 
   inc  cx 
   dec  di 
   dec  Cursor_Col 
@@KBBack:  call  SetCursor ;置光标位置 
   jmp  @@Input_Dec 
@@Save_Dig: and  al,0fh ;转换成二进制数 
   stosb ;保存 
   loop  @@Input_Dec ;接受下一个数字 
@@ASC_Dec: mov  ax,cx 
   pop  cx 
   pop  si 
   sub  cx,ax ;实际输入的数字位数 
   xor  bp,bp 
   xor  dx,dx 
   xor  ax,ax 
   jcxz  @@Save_Ret ;若直接回车,没有输入任何数字,按输入'0'处理 
   dec  cx ;实际输入的数字位数减1,准备把输入的这一串数字转换成二进制数 
   jcxz  @@One_Digit ;若输入的数字只有一位,转去直接保存这个二进制数 
   mov  bx,10 
@@Mul_Ten: lodsb 
   xor  ah,ah 
   add  ax,bp 
   mul  bx 
   mov  bp,ax 
   loop  @@Mul_Ten 
@@One_Digit: lodsb 
   xor  ah,ah 
   add  ax,bp 
@@Save_Ret: pop  di 
   cmp  @@Type_Data,'B' ;字节类型? 
   jz  $+5 
   stosw 
   jmp  $+3 
   stosb 
   pop  bx 
   pop  cx 
   pop  dx 
   pop  ds 
   ret 
@@Tmp_Cursor dw  ? ;起始光标位置 
@@Digits  db  ? ;十进制数字位数 
@@Type_Data db  'B' ;保存的数据类型。B=字节类型,W=字类型 
@@Save_Tmp db  7 dup(?) 
Input_Dec  EndP 
; -------------------------------------

3 楼

; 功能:把AX中的二进制无符号数转换成显式的十进制ASCII码,并送显示屏显示 
; 入口:AX=二进制数  
; 出口:在当前光标位置显示转换后的ASCII码数字  
Unsi_Dec_ASCII Proc  Near  
   push  dx  
   push  bx  
   push  di 
   mov   bx,10  
   lea   di,@@Temp_Save[5]  
   mov   BYTE PTR [di],'$'  
   dec   di  
   cld  
@@Divide:  xor   dx,dx  
   div   bx  
   or   dl,30h  
   mov   [di],dl  
   dec   di  
   test  ax,0ffffh  
   jnz   @@Divide  
   inc   di  
   push  di  
   pop   dx  
   mov   ah,9  
   int   21h  
   pop   di  
   pop   bx  
   pop   dx  
   ret  
@@Temp_Save  db   6 dup(?) 
Unsi_Dec_ASCII EndP 
; ------------------------------------- 
N   equ  3 ;学生成绩数字位数 
Prompt_Str  db    'Please input the name and score.',13,10,13,10,7 
   db  7,'Name',Name_Length-4+2 dup(20h) 
Score_Str  db  Num*8+9 dup(?) ;科目标题字符串缓冲区(预留8个科目的标题) 
Temp_Str  db  'Score?  ' 
Summation  db  'Summation' 
Temp_Cursor dw  ? ;输入、显示学生信息光标位置 
Press_Key   db     7,13,10,13,10,'The complated. Press any key to exit...$'  
Start:    push  cs 
   pop  ds 
   push  cs 
   pop  es ;使数据段、附加段与代码段同段 
   mov  @@Digits,N ;十进制数字位数 
   mov  @@Type_Data,'B' ;保存的数据类型。B=字节类型,W=字类型 

4 楼

; ------------------------------------- 
; 生成并显示输入学生姓名、各科成绩标题信息 
   lea  si,Temp_Str ;样板标题字符串地址 
   lea  di,Score_Str ;科目标题字符串地址 
   mov  cx,Num ;科目数 
   mov  dl,'1' ;科目序号初值 
   cld 
Title_Str: mov  [si][5],dl ;修改科目序号 
   push  cx 
   push  si 
   mov  cx,8 ;样板标题字符串长度 
   rep  movsb ;复制一个科目标题字符串 
   pop  si 
   pop  cx 
   inc  dl ;科目序号增1 
   loop  Title_Str ;下一个科目 
   lea  si,Summation 
   mov  cx,9 
   rep  movsb 
   mov  ax,0a0dh ;回车、换行 
   stosw 
   mov  al,'$' 
   stosb 
   Output Prompt_Str ;提示输入姓名、成绩 
   mov  al,Num ;科目数 
   mov  ah,8 ;每科标题长度 
   mul  ah 
   mov  cx,ax 
   add  cx,Name_Length ;加上姓名长度 
   add  cx,11 ;加总分标题长度 
   mov  dl,'-' 
@@L0:  call  Output_Chr ;显示一个字符 
   loop  @@L0 
   call  Output_CTLF ;输出一个回车、换行 
   call  GetCursor ;取光标位置 
   mov  dx,WORD ptr Cursor_Row 
   xchg  dh,dl 
   mov  Temp_Cursor,dx ;保存输入、显示学生信息光标位置 
; ------------------------------------- 
; 输入学生姓名、各科成绩 
   lea  di,List_Score ;姓名、成绩存放地址 
Input_Name: call  GetCursor ;取光标位置 
   push  di 
   lea  di,Buffer_Name[2] 
   mov  cx,5 
   mov  ax,2020h 
   rep  stosw 
   pop  di 
   lea  dx,Buffer_Name ;学生姓名输入缓冲区地址 
   mov  ah,0ah 
   int  21h 
   lea  si,Buffer_Name[1] 
   lodsb ;读入实际输入的字符个数 
   test  al,0ffh 
   jz  @@L1 ;若输入学生姓名时,直接回车,认为学生姓名、成绩等输入结束,转去计算输入的学生人数 
   mov  cx,Name_Length ;姓名字符数 
   push  di 
   rep  movsb ;写入姓名、成绩暂存地址保存 
   pop  di 
   add  di,LENGTH Name_Stud ;第1科成绩存放地址 
   add  Cursor_Col,Name_Length+2 ;列号加姓名长度再加2,开始输入成绩 
   call  SetCursor ;置光标位置 
   mov  cx,Num ;科目数,开始输入成绩 
   xor  bx,bx ;总成绩初值 
   push  di ;某科成绩存放地址 
Input_Score: call  Input_Dec ;输入成绩 
   add  bx,ax ;累加各科成绩 
   add  Cursor_Col,6 ;列号加6,输入下一科成绩光标位置 
   call  SetCursor ;置光标位置 
   loop  Input_Score ;输入下一科成绩 
   mov  [di],bx ;保存总成绩 
   mov  ax,bx 
   call  Unsi_Dec_ASCII ;把AX中的二进制无符号数转换成显式的十进制ASCII码,并送显示屏显示 
   pop  di 
   add  di,Num+Type Sum_Score ;下一名学生姓名、各科成绩存放地址 
   call  Output_CTLF ;输出一个回车、换行 
   jmp  Input_Name ;输入下一名学生姓名、各科成绩 
; ------------------------------------- 
; 计算输入的学生人数 
@@L1:  mov  ax,di 
   sub  ax,offset List_Score ;所有学生姓名、各科成绩所占内存容量 
   mov  bl,type Score_Stud ;每名学生信息所占内存容量 
   div  bl 
   mov  cx,ax ;CX=输入的学生人数 
   test  cx,cx 
   jnz  @@L00 
   jmp  Exit_Proc ;若未输入任何信息,直接结束程序 
; ------------------------------------- 
; 建立学生信息链表 
@@L00:  push  di ;保存链表地址 
   lea  ax,List_Score ;学生信息起始地址 
   push  cx 
@@L2:  stosw ;保存学生信息地址 
   add  ax,type Score_Stud ;每名学生信息所占内存容量 
   loop  @@L2 
   pop  cx 
   pop  si ;弹出链表地址给si 
   cmp  cx,2 
   jb  Exit_Proc ;若只输入了1名学生的信息,则无须排序和显示结果  
; ------------------------------------- 

5 楼

; 用冒泡排序法按总成绩降序排序 
   push  si ;入栈保存链表地址 
   push  cx ;保存学生人数 
   dec  cx ;准备用冒泡排序法排序 
@@Sorting:  push  cx ;入栈保存外循环次数 
     push  si ;入栈保存数组地址 
@@Compare:   push  si 
     pop   di ;当前数组元素地址赋给目的变址寄存器,以备交换之用 
   lodsw ;将当前数组元素读入累加器 
   mov  bx,ax 
   mov  ax,[bx.Sum_Score] ;将当前学生总成绩读入累加器AX 
   mov  bx,[si] ;相邻的下一个学生信息地址 
     cmp   ax,[bx.Sum_Score] ;当前学生总成绩与相邻的下一个学生总成绩相比较 
   jae  @@NextOne ;若大于或等于,不作数据交换,处理下一个数组元素 
         mov  ax,[di] ;若小于,读入当前学生信息链表节点 
         xchg  ax,[si] ;交换链表元素 
   mov  [di],ax ;保存数值较大者节点地址 
@@NextOne:  loop  @@Compare ;处理下一个数组元素 
   pop  si ;数组地址出栈 
     pop   cx ;外循环次数出栈 
     loop  @@Sorting ;下一趟比较 
; ------------------------------------- 
; 按总成绩降序显示所有学生姓名、各科成绩和总成绩 
   xor  bh,bh ;页号0 
   mov  ah,8 ;读光标位置的字符和属性 
   int  10h 
   mov  bh,ah ;字符属性 
   mov  cx,Temp_Cursor ;取输入、显示学生信息光标位置(滚动窗口左上角坐标) 
           mov  dx,184fh ;滚动窗口右下角坐标 
           mov  al,dh 
           inc  al 
           sub  al,ch ;滚动行数 
           mov  ah,6 ;显示内容上滚 
           int  10h 
   mov  dx,Temp_Cursor ;取输入、显示学生信息光标位置 
           xor   bx,bx 
           mov  ah,2 ;设置光标位置 
           int   10h 
     pop  cx ;弹出学生人数 
     pop  si ;弹出链表地址 
@List_Score: push  cx ;保存学生人数 
   call  GetCursor ;取光标位置 
   lodsw ;读入链表的一个节点 
   push  si ;入栈保存链表地址 
   mov  si,ax 
   push  si ;入栈学生信息地址 
   lea  si,[si.Name_Stud] ;姓名地址 
   mov  cx,Name_Length ;姓名字符串长度 
@@Dsip_Name: lodsb ;读入一个字符 
   cmp  al,0dh ;回车符? 
   jz  @@L3 ;是,姓名显示结束,开始显示成绩 
   mov  dl,al 
   call  Output_Chr ;显示一个字符 
   loop  @@Dsip_Name ;下一个字符 
@@L3:  add  Cursor_Col,Name_Length+2 ;列号加姓名长度再加2,开始显示成绩 
   call  SetCursor ;置光标位置 
   pop  si ;弹出学生信息地址 
   lea  si,[si.Score] ;各科分数地址 
   mov  cx,Num ;科目数 
@Disp_Score: lodsb ;读入一科分数 
   xor  ah,ah 
   call  Unsi_Dec_ASCII ;把AX中的二进制无符号数转换成显式的十进制ASCII码,并送显示屏显示 
   add  Cursor_Col,8 ;列号加8,显示下一科分数光标位置 
   call  SetCursor ;置光标位置 
   loop  @Disp_Score ;下一科分数 
   lodsw ;读入各科总分 
   call  Unsi_Dec_ASCII ;把AX中的二进制无符号数转换成显式的十进制ASCII码,并送显示屏显示 
   call  Output_CTLF ;输出一个回车、换行 
   pop  si ;弹出链表地址 
     pop  cx ;弹出学生人数 
   loop  @List_Score ;下一个节点(学生信息) 
; ------------------------------------- 
Exit_Proc: Output Press_Key ;提示操作完成,按任意键结束程序 
   mov  ah,1 
   int  21h 
   mov  ah,4ch ;结束程序 
   int  21h 
even 
Buffer_Name  db  9,?,10 dup(?) ;学生姓名输入缓冲区 
List_Score: ;姓名、成绩暂存地址 
Code   ENDS 
   END   Start ;编译到此结束

我来回复

您尚未登录,请登录后再回复。点此登录或注册