算法实现1: 输入8个学生的个人信息,信息的数据结构是 NO.: Name: Score1: 成绩分别输入为: 98,45,23,78,90,75,68,66
根据成绩的分数,从大到小输出每一个学生的所有个人信息
代码:
.model small ;堆栈段名 stack,默认大小 1024 字节,这里是 200h 字节
.data ;数据段名_data
student struc ;学生的数据结构,32 字节,2^5,便于计算地址
xname db 14 dup('$')
num dw 0
score dw 0 ;为了保存1位小数,以10倍值保存
student ends
stu_size equ 32 ;32=2^5
stu_db student 100 dup(<>) ;声明100 名学生的空间的结构体stu_db
stu_num db 0 ;已保存的学生人数
stu_seq db 100 dup('$') ;排序信息,排序操作在序列中进行,排序结果体现在序列中
welcome db '-----Student Information Mannagement System-----',0dh,0ah ;打印菜单
db '------------------------------------------------',0dh,0ah;
db '0. Add Information.',0dh,0ah ;0. 录入学生成绩(十进制形式)
db '------------------------------------------------',0dh,0ah;
db '1. Sort by the scores of students.',0dh,0ah ;1.按成绩排序显示
db '------------------------------------------------',0dh,0ah;
db '2. Exit.',0dh,0ah ;2.退出
db '------------------------------------------------',0dh,0ah;
db 'please select one'
db '$'
msg1 db 'name:','$'
msg2 db 'no:','$'
msg3 db 'score:','$'
m_str_l db 0dh,0ah,'please input your ','$'
m_num_l db 0dh,0ah,'please input your ','$'
table dw CASE0,CASE1,CASE2
buflen db 100 ;输入缓冲区大小 100
aclen db ? ;实际输入长度
buf db 100 dup(0),'$' ;实际缓冲区
bufrear equ offset buf+100 ;缓冲区尾
.code ;代码段名_text
start:
ps macro str ;打印字符串,要求以'$'结尾
push ax
push dx
lea dx,str
mov ah,9
int 21h
pop dx
pop ax
endm
pc macro ch ;打印字符
push ax
push dx
mov dl,ch
mov ah,2
int 21h
pop dx
pop ax
endm
endl macro ;打印'\n'
pc 0dh
pc 0ah
endm
scs macro ;从键盘输入字符串,保存在buf中,串长aclen
lea dx,buflen
mov ah,10
int 21h
endm
scc macro ;从键盘输入字符,保存在al
mov ah,1
int 21h
endm
memcpy macro dest,src,len ;经典的内存拷贝
push ax
push cx
push si
push di
mov ax,ds
mov es,ax ;串操作di要用到附加段
mov cl,len
mov ch,0
lea si,src
lea di,dest
cld
rep movsb
;mov [di],'
pop di
pop si
pop cx
pop ax
endm
;使bx指向编号为ax的学生单元
;寄存器:ax,bx,cx
GET_STU macro
push ax
push cx
lea bx,stu_db
mov cl,5
shl ax,cl ;?????????
add bx,ax ;bx指向这个学生的存储单元
pop cx
pop ax
endm
mov ax,@data
mov ds,ax
WELC: ;调用ps函数打印welcome数据段
endl
ps welcome
pc ':'
;输入选项
scc ;ascii码保存在al
endl
endl
mov ah,0
mov bx,ax
sub bx,'0'
cmp bx,5
jbe CASE0TO5 ;bx寄存器不高于5则转移到CASE0T05
jmp WELC
CASE0TO5:
shl bx,1
jmp table[bx] ;基址寻址
CASE0: ;录入学生成绩(十进制形式)
call ins_stu
jmp WELC
CASE1: ;按成绩排序显示
call score_sort
call print_seq
jmp WELC
CASE2:
mov ah,4ch ;结束
int 21h
;ins_stu:输入学生信息
;入口:stu_num已有学生人数,即最新空白编号
;出口:stu_db
;存储单元:stu_db,stu_num
ins_stu proc near
push ax
push bx
push cx
push dx
mov al,stu_num
mov ah,0
;确定存放在第几个位置
lea bx,stu_db
mov cl,5
shl ax,cl
add bx,ax ;bx指向空白单元
input_name:
ps m_str_l ;m_str_l db 0dh,0ah,'(Length < 14 bytes) ','$'
ps msg1 ;msg1 db 'name:','$'
scs
cmp aclen,14
jae input_name ;大于等于跳转至重新输入name
memcpy [bx].xname,buf,aclen;否则拷贝buf长度为aclen的字符串到stu_db结构体下的xname
endl
input_class:
ps m_num_l
ps msg2
scs
call str2num ;调用str2num:将数字由字符串转成数值
mov [bx].num,ax
endl
ps m_num_l
ps msg3
scs
call score_fmt ;调用score_fmt:将分数格式存储
mov [bx].score,ax
endl
inc stu_num ;增加学生记录
pop dx
pop cx
pop bx
pop ax
ret
ins_stu endp
;pnum:以十进制形式输出一个无符号数
;入口:ax需要输出的正数
;出口:
;存储单元:
pnum proc near
push ax
push bx
push cx
push dx
mov bx,bufrear
dec bx
mov bx,'$'
OUTLOOP:
or ax,ax
jz OUTLOOPFIN ;ax为零
mov dx,0
mov cx,10
div cx
add dl,'0'
dec bx
mov byte ptr [bx],dl
jmp OUTLOOP
OUTLOOPFIN:
cmp bx,offset [bufrear-1] ;输出0
jne PRINT_NUM
dec bx
mov BYTE ptr [bx],'0'
PRINT_NUM:
mov dx,bx
mov ah,9
int 21h
pop dx
pop cx
pop bx
pop ax
ret
pnum endp
;pscore:以十进制形式输出带一位小数的分数
;入口:ax需要输出的正数
;出口:
;存储单元:
pscore proc near
push ax
push bx
push cx
push dx
mov bx,bufrear
OUTLOOP2:
or ax,ax
jz OUTLOOPFIN2
mov dx,0
mov cx,10
div cx
add dl,'0'
dec bx
mov byte ptr [bx],dl
jmp OUTLOOP2
OUTLOOPFIN2:
cmp bx,offset [bufrear-1] ;x要改成0x,以便小数格式输出
je S0X
cmp bx,offset [bufrear] ;空要改成00,以便小数格式输出
jne PRINT_SCORE
S00:
;==,为空
dec bx
mov BYTE ptr [bx],'0'
S0X:
dec bx
mov BYTE ptr [bx],'0'
PRINT_SCORE:
mov dx,bx
mov bx,bufrear
dec bx
mov cl,[bx] ;暂存小数
mov bx,'$' ;mov dx,bx
mov ah,9
int 21h
pc '.'
pc cl
pop dx
pop cx
pop bx
pop ax
ret
pscore endp
;pstu:输出学生信息
;入口:ax存储编号
;出口:
;存储单元:
pstu proc near
push ax
push bx
push cx
GET_STU
ps msg1
ps [bx].xname;
pc ' '
ps msg2
mov ax,[bx].num
call pnum
pc ' '
ps msg3
mov ax,[bx].score
call pscore
endl
pop cx
pop bx
pop ax
ret
pstu endp
;str2num:将数字由字符串转成数值
;入口:buf
;出口:ax
;存储单元:buf缓冲区,aclen缓冲区内容长度
str2num proc
push bx
push cx
push si
mov ax,0
mov cl,aclen
mov ch,0
lea si,buf
GET_NUM:
mov bl,[si]
mov bh,0
add ax,bx
sub ax,'0'
inc si
loop GET_NUM
pop si
pop cx
pop bx
ret
str2num endp
;score_fmt:将分数格式存储
;入口:buf
;出口:ax
;存储单元:buf缓冲区,aclen缓冲区内容长度
score_fmt proc
push bx
push cx
push dx
push si
mov ax,0
mov cl,aclen
mov ch,0
mov dx,0
lea si,buf
GET_SCORE:
cmp BYTE ptr [si],'.' ;这个类型很重要
jnz MUL_DEX ;不是小数点
mov dx,1 ;发现小数点
inc si
loop GET_SCORE
MUL_DEX:
mov bl,10
mul bl
mov bl,[si]
mov bh,0
add ax,bx
sub ax,'0'
inc si
loop GET_SCORE
cmp dx,0
jnz END_SCORE
mov bl,10
mul bl
END_SCORE:
pop si
pop dx
pop cx
pop bx
ret
score_fmt endp
;print_seq:根据序列stu_seq输出列表
;输入:stu_seq
;输出:
;存储单元:stu_seq
print_seq proc near
push ax
push bx ;stu_seq保存了编号序列,以'$'结束
lea bx,stu_seq
PRINT_SEQ_BEGIN:
mov al,[bx]
cmp al,'$'
jz PRINT_SEQ_END
mov ah,0
call pstu
inc bx
jmp PRINT_SEQ_BEGIN
PRINT_SEQ_END:
pop bx
pop ax
ret
print_seq endp
;score_sort:按成绩排序
;输入:stu_seq
;输出:stu_seq
;存储单元:
score_sort proc near
push bx
push dx
mov dl,0
lea bx,stu_seq
SCORE_BEGIN:
cmp dl,stu_num
jae SCORE_END
mov BYTE ptr [bx],dl
inc bx
inc dl
jmp SCORE_BEGIN
SCORE_END:
mov BYTE ptr [bx],'$'
;stu_seq保存了按输入顺序的序列,以'$'结束
cmp stu_num,1 ;学生数小于等于1,没必要排序
jle NON_SCORE
mov cl,stu_num ;循环次数,内存量不能直接减
dec cl
mov ch,0
SLOOP1:
mov di,cx ;暂存外循环cx
lea bx,stu_seq ;指向第一个序号
SLOOP2:
mov al,BYTE ptr [bx]
mov ah,0
push bx
GET_STU
mov dx,[bx].score ;dx前一个序列号对应的学号
pop bx
mov al,BYTE ptr [bx+1]
push bx
GET_STU
cmp dx,[bx].score ;[bx].num后一个序列号对应的学号
pop bx
jae SCONTI
mov al,BYTE ptr [bx] ;小于则交换两个序列号
;call pnum
;endl
xchg al,BYTE ptr [bx+1]
;call pnum
;endl
mov BYTE ptr [bx],al
SCONTI:
inc bx ;下一个序列号
loop SLOOP2
mov cx,di ;恢复外循环
loop SLOOP1
NON_SCORE:
pop dx
pop bx
ret
score_sort endp
END START
运行截图: