Shall be saved as .asm file and compile -> .obj -> .exe (16bit) and run in command line window.

Hello World显示字符

  1. DSEG SEGMENT
  2. STRING DB 'HELLO,WORLD!',0DH,0AH,'$' ;定义显示的字符
  3. DSEG ENDS
  4. CSEG SEGMENT
  5. ASSUME CS:CSEG, DS:DSEG
  6. START: MOV AX,DSEG
  7. MOV DS,AX
  8. LEA DX,STRING ;获取显示字符串的首地址
  9. MOV AH, 09H ;09H为调用显示功能
  10. INT 21H
  11. MOV AH,4CH ;调用返回dos
  12. INT 21H ;软件中断,返回dos
  13. CSEG ENDS
  14. END START

5位数字十进制相加 Extremely buggy

DATAS SEGMENT
DATA1 DB 5 DUP(0)
    DATA2 DB 5 DUP(0)
    DATA3 DB 6 DUP(0)
    addsign db ' + ' ,'$' 
    equalsign db ' = ' ,'$'
    DATAS ENDS
    ;
    CODES SEGMENT
    ASSUME CS:CODES,DS:DATAS
    START:
MOV AX,DATAS
MOV DS,AX
LEA BX,DATA1
MOV CX,5
    INADD1:MOV AH,01H
        INT 21H
        MOV [BX],AL
        INC BX
        LOOP INADD1
        LEA DX,addsign    ;display add sign
        MOV AH,09H
            INT 21H
            LEA SI,DATA2
            MOV CX,05H
            INADD2:MOV AH,01H
                INT 21H
                MOV [SI],AL
                INC SI
                LOOP INADD2
                LEA DX,equalsign    ;display equal sign
                MOV AH,09H
                    INT 21H          ;return to dos
                    LEA BX,DATA1+4
                        LEA SI,DATA2+4
                        LEA DI,DATA3+5
                        MOV CX,5
                        CLC        ;clear CF flag
                        L1:MOV AL,[BX]
                        ADC AL,[SI]
                        AAA
                        PUSHF
                        OR AL,30H    ;AL->ASCII
                        POPF
                        MOV [DI],AL
                        DEC DI
                        DEC BX
                        DEC SI
                        LOOP L1
                        MOV CL,6    
                            JNC OUT1    ;没有进位直接输出
                            MOV byte ptr[DI],31H    ;有进位给最高位赋1
                            OUT1:
MOV DL,[DI]
INC DI
MOV AH,02H
    INT 21H
    LOOP OUT1
    MOV AH,4CH
    INT 21H
    CODES ENDS
    END START
DATA SEGMENT
APP DB 35H,34H,33H,32H,31H,2BH,34H,35H,34H,33H,32H,3DH,0DH,0AH,'$ '
DATA1 DB 01H,02H,03H,04H,05H
DATA2 DB 02H,03H,04H,05H,04H
SUM DB 5 DUP(?),'$ '
;
CODE SEGMENT
           ASSUME CS:CODE,DS:DATA
START: MOV AX,DATA
MOV DS,AX
LEA DX,APP
MOV AH,09H
INT 21H                     ;这里先把加数和被加数以加法的格式显示出来
MOV SI,OFFSET DATA1
MOV DI,OFFSET DATA2
MOV BX,OFFSET SUM
XOR CX,CX
MOV CL,5                  ;给定加法位数
GO: MOV AL,[SI]
ADC AL,[DI]
AAA
PUSHF                       ;压入堆栈保护标志位
ADD SI,1
ADD DI,1
MOV [BX],AL
ADD [BX+4],30H            ;将结果调整到ASCII码的形式,方便显示
DEC BX
POPF
LOOP GO
LEA DX,SUM
MOV AH,09H
INT 21H
MOV AH,4CH
INT 21H
CODE ENDS
           END START

16-2进制转换

CRLF MACRO
MOV AH,02H
MOV DL,0DH
INT 21H
MOV AH,02H
MOV DL,0AH
INT 21H
ENDM
DATA SEGMENT
MARK DB ?
MESS DB'INPUT:$'
ERROR DB 0DH,0AH,'INPUT IS ERROR!',0DH,0AH,'$'
DATA ENDS

STACK SEGMENT
STA DW 32 DUP(?)
STACK ENDS
CODE SEGMENT
    ASSUME CS:CODE,DS:DATA,SS:STACK
BEGIN:
MOV AX,DATA
MOV DS,AX
HEAD:CRLF
MOV MARK,0H
MOV AH,09H
LEA DX,MESS
INT 21H
CALL INPUTNUM
CMP MARK,01H
JE HEAD;
MOV CX,0010H
MOV BX,DX
SHOW:ROL BX,1
MOV DL,BL
AND DL,01H
ADD DL,30H
MOV AH,02H
INT 21H
LOOP SHOW
JMP HEAD
FIN:MOV AX,4C00H
INT 21H
INPUTNUM PROC NEAR
XOR DX,DX
GO:MOV AH,01H
INT 21H
CMP AL,0DH
JE HCHH
CMP AL,20H
JE FIN
CMP AL,30H
JB WRONG
SUB AL,30H
CMP AL,0AH
JB BINGO
CMP AL,11H
JB WRONG
SUB AL,07H
CMP AL,0FH
JBE BINGO
CMP AL,2AH
JB WRONG
CMP AL,2FH
JA WRONG
SUB AL,20H
BINGO:
MOV CL,04H
SHL DX,CL
XOR AH,AH
ADD DX,AX
JMP GO
WRONG:MOV AH,09H
MOV DX,OFFSET ERROR
INT 21H
MOV MARK,01H
HCHH:PUSH DX
CRLF
POP DX
RET
INPUTNUM ENDP
CODE ENDS
END BEGIN

屏幕显示可移动图形

DATA SEGMENT
UP DW 0,0DBDBH,0,0808H,0808H,0808H       ;画炮口向上的坦克
DB 0AH
DW 0DBDBH,0DBDBH,0DBDBH,0808H,0808H,0808H
DB 0AH
DW 0DBDBH,0,0DBDBH
DOWN DW 0DBDBH,0,0DBDBH,0808H,0808H,0808H    ;画炮口向下的坦克
DB 0AH
DW 0DBDBH,0DBDBH,0DBDBH,0808H,0808H,0808H
DB 0AH
DW 0,0DBDBH,0
LEFT DW 0,0DBDBH,0DBDBH,0808H,0808H,0808H    ;画炮口向左的坦克
DB 0AH
DW 0DBDBH,0DBDBH,0,0808H,0808H,0808H
DB 0AH
DW 0,0DBDBH,0DBDBH
RIGHT DW 0DBDBH,0DBDBH,0,0808H,0808H,0808H   ;画炮口向右的坦克
DB 0AH
DW 0,0DBDBH,0DBDBH,0808H,0808H,0808H
DB 0AH
DW 0DBDBH,0DBDBH,0
LENTH DW 32   ;画坦克所需字节数
FWD DW 0      ;坦克方向
LOCA DB 0BH,0DH,25H,2AH   ;坦克的位置
DATA ENDS

CODE SEGMENT
ASSUME CS:CODE,DS:DATA
START:MOV AX,DATA
MOV DS,AX 
MOV ES,AX
LEA BP,UP       ;取段地址

LOP:CALL CLEAR       ;清屏

MOV AH,08H       ;输入方向
INT 21H

CALL COMPARE      ;对输入字符进行处理

MyESC:MOV AH,4CH          ;退出
INT 21H

COMPARE PROC NEAR
CMP AL,1BH       ;退出
JE MyESC

CMP AL,'w'       ;是否输入向上走
JNE L2
MOV BX,FWD       ;比较初始方向
CMP BX,0
JNE L1           ;如果初始方向不为上,则坦克转向
CMP LOCA[0],0    ;如果初始方向为上,则在不撞墙的情况下前进一格
JE L1
DEC LOCA[0]      ;坦克上行减一
DEC LOCA[1]      ;坦克下行减一
L1:MOV FWD,0         ;调整坦克方向
LEA BP,UP        ;将画炮口向上的坦克的字符串偏移地址赋给寄存器
JMP LOP

L2:CMP AL,'s'         
JNE L4
MOV BX,FWD
CMP BX,1
JNE L3
CMP LOCA[1],18H
JE L3
INC LOCA[0]
INC LOCA[1] 
L3: MOV FWD,1
LEA BP,DOWN
JMP LOP

L4:CMP AL,'a'
JNE L6
MOV BX,FWD
CMP BX,2 
JNE L5
CMP LOCA[2],1
JE L5
DEC LOCA[2]
DEC LOCA[2]
DEC LOCA[3]
DEC LOCA[3]
L5:MOV FWD,2 
LEA BP,LEFT
JMP LOP

L6:CMP AL,'d'
JNE L8
MOV BX,FWD
CMP BX,3
JNE L7
CMP LOCA[3],4EH
JE L7
INC LOCA[2]
INC LOCA[2]
INC LOCA[3]
INC LOCA[3]
L7:MOV FWD,3
LEA BP,RIGHT
L8:JMP LOP
RET
COMPARE ENDP

CLEAR PROC NEAR
MOV AX,0600H    ;清屏
MOV BH,0F4H
MOV CX,1
MOV DX,184EH
INT 10H

MOV DH,LOCA[0]  ;取坦克上行左列为起始点画坦克
MOV DL,LOCA[2]
MOV AX,1301H
MOV BH,00
MOV BL,0F9H
MOV CX,LENTH
INT 10H

RET
CLEAR ENDP 

CODE   ENDS
END START

屏幕输入内容并自动滚动

CODES SEGMENT
    ASSUME CS:CODES
;主程序
Main  proc  far

    call  Initializing
    call  get_char
    ret
Main  endp
    ;屏幕初始化
Initializing  proc  near
    push  ax
    push  bx
    push  cx
    push  dx
     ;设置外窗口属性
    MOV   AH,7                ;功能:屏幕初始化
    MOV   AL,0                ;page
    MOV   BH,70H            ;白底黑字
    MOV   CH,1                ;row左上
    MOV   CL,2                ;column左上
    MOV   DH,23                ;row右下
    MOV   DL,77                ;column右下
    INT   10H                ;BIOS显示操作中断

    ;设置内窗口属性
    MOV   AH,7                ;功能:屏幕初始化
    MOV   AL,0                ;page
    MOV   BH,3FH            ;浅青色底白字
    MOV   CH,2                ;row左上
    MOV   CL,4                ;column左上
    MOV   DH,22                ;row右下
    MOV   DL,75                ;column右下
    INT   10H                ;BIOS显示操作中断

    ;设置光标类型(大小)
    MOV   CH,12                ;光标起始行
    MOV   CL,13                ;光标结束行
    MOV   AH,1                ;设置光标类型
    INT   10H                ;DOS中断:显示操作
    ;初始化光标位置
    MOV   DH,22                ;屏幕显示行
    MOV   DL,4                ;屏幕显示列
    MOV   BH,0                ;显示页号
    MOV   AH,2                ;置光标位置
    INT   10H                ;BIOS显示操作中断

    pop   dx
    pop   cx
    pop   bx
    pop   ax
    ret
Initializing  endp
;键盘输入,直到Esc退出
get_char  proc  near
    push  ax
    push  dx

    mov   ah,1            ; 功能:从键盘输入一个字符并回显
    int   21h

    cmp   al,1bh            ; 判断按键是否ESC√
    jz    exit

    cmp   al,0DH            ; 判断是否为回车键(要注意回车后不返回,而是等待继续输入)
    jz    EnterDeal            ; 调转 回车键处理

    mov   ah,3            ; 读取当前光标位置
    ;mov  bh,0            ; 页号
    int   10h            ; BIOS显示操作中断

    cmp   dl,76            ; 判断是否最后一列(75+1)√(可用于设置字符显示宽度)
    jz    LastColumn        ; 跳转 末列处理

    loop  get_char            ; 继续输入

    pop   dx
    pop   ax

;退出程序
exit:
    mov   ah,4ch
    int   21h            ;DOS中断
get_char  endp
;回车键处理-----------------;(把回车控制到内窗口-不处理会跳到屏幕左边界)
EnterDeal proc  near
    push  ax
    push  dx

    mov   ah,3            ; 读取当前光标位置
    ;mov  bh,0            ; 页号
    int   10h            ; BIOS显示操作中断

    mov   ah,2            ; 功能:置光标位置
    ;mov  dh,?            ; 保持当前行
    mov   dl,4            ; 光标置内窗口左边界
    ;mov  bh,0            ; 页号
    int   10h            ; BIOS显示操作中断

    jmp   LastLine            ; 继续末行判断

    pop   dx
    pop   ax
    ret                ; 返回主程序
EnterDeal  endp
;末列处理
LastColumn     proc  near
    push  ax
    push  dx

    mov   ah,3            ; 读取当前光标位置
    ;mov  bh,0            ; 页号
    int   10h            ; BIOS显示操作中断

    mov   ah,2            ; 功能:置光标位置
    add   dh,1            ; 光标置下一行
    mov   dl,4            ; 光标置内窗口左边界
    ;mov  bh,0            ; 页号
    int   10h            ; BIOS显示操作中断

    jmp   LastLine            ; 继续末行判断

    pop   dx
    pop   ax
    ret                ; 返回主程序
LastColumn  endp
;末行判断-------------------; 末行(22+1)需要卷屏并上移光标
LastLine  proc  near
    push  ax
    push  dx

    mov   ah,3            ; 读取当前光标位置
    ;mov  bh,0            ; 页号
    int   10h            ; BIOS显示操作中断

    cmp   dh,23            ; 判断是否最后一行(22+1)
    jne   get_char                ; 否:继续输入

    ;-----------------------        ; 是:卷屏1行并上移光标
    call  scroll_screen             ; 调用屏幕滚动

    mov   ah,3            ; 读取当前光标位置
    ;mov  bh,0            ; 页号
    int   10h            ; BIOS显示操作中断

    mov   ah,2            ; 功能:置光标位置
    mov   dh,22            ; 光标置内窗口左边界
    mov   dl,4            ; 光标置内窗口左边界
    int   10h            ; BIOS显示操作中断

    pop   dx
    pop   ax
    jmp   get_char                ; 继续输入
Lastline  endp
;屏幕每次上卷1行----------------          ; 屏幕滚动必须要设置窗口滚动的范围,即cx,dx
scroll_screen    proc  near
    push  ax
    push  bx
    push  cx
    push  dx

    mov      al,1            ; 上卷的行数
    mov      bh,2FH        ; 
    mov   ch,2
    mov   cl,4
    mov   dh,22            ; 整屏滚动
    mov   dl,75
    mov      ah,6            ; 功能:屏幕上卷
    int   10h            ; BIOS显示操作中断

    pop   dx
    pop   cx
    pop   bx
    pop   ax
    ret                ; 返回调用程序
scroll_screen  endp
CODES ENDS
END   Main

学生成绩数据处理

info STRUC
           s_class DB 4,?,2 DUP(' ')
    s_id DB 7,?,5 DUP(' ')
    s_name DB 8,?,6 DUP(' ')
    s_score DB 3 DUP(' '),'.0$'    ;分数需特殊处理
info ENDS

data SEGMENT
    num_mes DB 0dh,0ah,'Please input the number of student(1-99):$'
    cLass_mes DB 0dh,0ah,'CLASS(within 2 bits,end with dollar)',0dh,0ah,'$'                        
        id_mes DB 0dh,0ah,'ID (within 4 bits,end with dollar)',0dh,0ah,'$'              
    name_mes DB 0dh,0ah,'NAME (within 5 bits,end with dollar)',0dh,0ah,'$'   
    score_mes DB 0dh,0ah,'SCORE (xx.x or xx,end with dollar)',0dh,0ah,'$'    ;成绩输入整数或有一位小数
    ave_mes DB 0dh,0ah,'AVERAGE SCORE:$'
    stand_mes DB 0dh,0ah,'<60 60-70 70-80 80-90 90-100:',0dh,0ah,'$'
     line DB 0dh,0ah,'$'
    blank DB '   $'

    student info 99 DUP(<>)     ;数组
    temp DB 8,?,6 DUP(' ')      ;缓存输入的分数
    s_num DW 0                  ;存储学生数
    sum_score DW 0              ;存储总分
        ;用于统计各个分数段人数
        sco_60 DB        '0'
        sco_70 DB        '0'
        sco_80 DB        '0'
        sco_90 DB        '0'
        sco_100 DB       '0'                     
    sscore DB '100''$'        ;要显示的分数,初值为满分100
    n DW 10                ;十进制数权重
    ssnum DB 3 DUP(0)
    buffer1 DW 0                ;存储分数的整数位数据
    buffer2 DW 0                ;存储分数的小数位
data ENDS

code SEGMENT
ASSUME CS:code,DS:data
start:
main  PROC FAR
    MOV AX,data
    MOV DS,AX
;--------------------------------输入,存储信息

INPUTE: LEA AX,num_mes
    MOV DX,AX
    MOV AH,09h
    INT 21h        ;显示num_mes  

;--------------------------------获得学生人数begin
    XOR BX,BX       ;清空BX
in_num:
    MOV AH,01          ;输入字符
     INT 21h;            
    CMP AL,0dh         ;判断是否输入回车
    JE  new_l          ;若输入结束则跳转
      AND AL,0fh         ;输入未结束 转换成非压缩的BCD码
     MOV ssnum[BX],AL
     INC BX             ;输入未结束,则继续输入
     JMP in_num
new_l:    
    CMP BX,3       ;输入数大于99,重新输入
    JNC INPUTE    
        CMP BX,2           ;输入学生数大于10,还是小于10
        JZ INPUTE_2        ;学生数大于10
        JMP INPUTE_l       ;学生数小于10,大于0

INPUTE_2:      
    MOV AH,ssnum        ;输入数为两位数   
    MOV AL,ssnum[1]                
        AAD                 ;BCD码转换为二进制数 
INPUTE_l:
    MOV AL,ssnum
    XOR AH,AH        
    MOV s_num,AX     
 ;-----------------------------------------录入信息begin
    MOV CX,s_num          ;CX存放学生数
    LEA BX,student            ;变量student的首地址传给BX
loop1:                            ;循环读取每个学生信息
    PUSH CX              ;CX压栈

         LEA DX,class_mes          ;显示class_mes
    MOV AH,09h
    INT 21h ;

    MOV DX,BX                 ;BX存放info结构体的s_class的地址    
    MOV AH,0ah                ;输入学号到info结构体的s_class
    INT 21h

          LEA DX,id_mes             ;显示id_mes
    MOV AH,09h
    INT 21h ;

    ADD BX,4
          MOV DX,BX                                  
    MOV AH,0ah                ;输入学号到info结构体的s_id
    INT 21h

    LEA DX,name_mes           ;显示name_mes
    MOV AH,09h
    INT 21h ;

    ADD BX,7                  ;BX存放info结构体的s_name的地址    
    MOV DX,BX                 ;输入姓名到info结构体的s_name
    MOV AH,0ah
    INT 21h

    LEA DX,score_mes          ;显示score_mes
    MOV AH,09h
    INT 21h 
    ADD BX,8                  ;BX存放info结构体的s_score的地址
qqq:
    LEA DX,temp               ;输入成绩到缓冲区
    MOV AH,0ah
    INT 21h
    XOR DI,DI                 ;清空DI
    MOV AL,temp[1]
    XOR AH,AH                 ;清空AH
    MOV DI,AX                 ;DI中存放输入的字符数
    MOV CX,DI                 ;循环次数为输入字符数
    MOV SI,DI          ;SI中存放输入的字符数
    INC SI
jiance:
    CMP temp[SI],'.'          ;检测是否输入小数
    JE xiaoshu              ;若是,转到xiaoshu
    DEC SI                  ;若否,继续检测下一位
    LOOP jiance

    MOV SI,2          ;输入为整数
    JMP ddd
xiaoshu:
    MOV SI,4          ;输入有小数
ddd:
    MOV AL,temp[DI]          ;将该位成绩由缓冲区输入到内存info结构体对应学生成绩项
    MOV [BX+SI],AL
    CMP DI,2          ;数据位比较完成 
    JE zzz
    DEC DI              ;输入下一位
    DEC SI
    JMP ddd
zzz:
    POP CX              ;CX出栈
    CALL get_score          ;求得成绩
    ADD BX,6
    LOOP loop1          ;下一个学生
;----------------------------------------------------结束录入

    MOV AX,sum_score      ;学生总成绩
    XOR DX,DX
    DIV s_num          ;除以学生数
    MOV sum_score,AX          ;得到平均数 仍存储于sum_score

;--------------------------------------------排序,按成绩由大到小
    MOV CX,s_num
    DEC CX
    CMP CX,0        ;若只有一个学生,直接输出
    JE oout
    LEA BX,student        ;否则将学生数组的地址给BX
lll1:                           ;冒泡排序
    MOV DX,CX        ;保存外层循环次数,外层循环次数是数组个数减1
    PUSH BX
lll2:
    PUSH CX            
    MOV DI,BX        ;保存当前学生地址
    ADD BX,19        ;下一个学生
    MOV CX,5        ;每个学生成绩有5位
    XOR SI,SI        ;清空SI
lll3:                ;按位比较两同学的成绩,由高位到低位
    MOV AL,[BX+SI]        ;当前学生成绩赋值给AL
    CMP AL,[BX+SI+25]    ;比较当前学生与下一学生的成绩
    JB swap                 ;若小于,交换
         JA next_stu             ;若大于,比较下一个学生
         INC SI            ;否则,比较下一位
         LOOP lll3
swap:                ;交换两学生全部信息
        XOR CX,CX         ;清空CX
        MOV CX,26        ;一个学生的信息共占25字节
        XOR SI,SI        ;清空SI
        MOV BX,DI        ;恢复刚才比较的学生的地址
sswap:
      MOV AL,[BX+SI]          ;bx用作交换中的计数
        XCHG AL,[BX+SI+25]     ;按位交换      
        MOV [BX+SI],AL       
        INC SI
        LOOP sswap
next_stu:            ;下一个学生
         POP CX
        MOV DI,BX
        ADD BX,25
     LOOP lll2
    POP BX                          
        MOV CX,DX        ;恢复外层循环次数
    LOOP lll1

;---------------------输出-------------
oout:
    MOV CX,s_num    ;CX存放学生数
    XOR BX,BX    ;BX清空
    LEA BX,student    ;变量student的首地址给BX
    ADD BX,2
    MOV AH,09h    ;显示字符串
    CALL lline    ;空行
xianshi:
    CALL lline
    MOV DX,BX    ;DX指向要显示的学生
    INT 21H 

        CALL bblank     ;空格
    ADD BX,4    ;显示学号
    MOV DX,BX
    INT 21H 

    CALL bblank     ;空格
    ADD BX,7    ;显示姓名
    MOV DX,BX
    INT 21H 

    CALL bblank
    ADD BX,6    ;显示成绩
    MOV DX,BX
    INT 21H 
    CALL get_stand

    ADD BX,8    ;显示下一个学生
    LOOP xianshi

    CALL lline
    LEA AX,stand_mes
    MOV DX,AX
    MOV AH,09h
    INT 21h     ;显示stand_mes

          MOV DL,sco_60    ;显示表示成绩小于60分人数的字符
          MOV AH,2
    INT 21h
    CALL bblank
    MOV DL,sco_70    ;显示60-70分人数
          MOV AH,2
    INT 21h
    CALL bblank
          CALL bblank     
    MOV DL,sco_80    ;显示70-80分人数
          MOV AH,2
    INT 21h
    CALL bblank
        CALL bblank     
    MOV DL,sco_90    ;显示80-90分人数
          MOV AH,2
    INT 21h
    CALL bblank
          CALL bblank     
    MOV DL,sco_100    ;显示90-100分人数
          MOV AH,2
          INT 21h

    CALL get_ave    ;显示平均成绩

    MOV AH ,1    ;输入一个字符,方便显示结果,无实际意义
        INT 21h


    MOV AX,4c00h    ;停机
    INT 21H

;----------------------------------------------------------------------
get_score  PROC  NEAR 

    MOV SI,2
loop4:
    MOV AL,temp[SI]
    CMP AL,'.'        ;比较当前位是否是小数点
     JE ppoint               ;若是,转到ppoint
    CMP AL,'$'        ;比较当前位是否结束
    JE eend               ;若是,转到eend
      AND AX,000fh           ;换成非压缩的BCD码,求得成绩
      XCHG AX,buffer1        ;输入到分数整数位
    MUL n            ;AL中的数乘以十进制权重
    ADD buffer1,AX
    INC SI            ;比较下一位
      JMP loop4

ppoint:
      INC SI            ;比较下一位
      MOV AL,temp[SI]             
    CMP AL,'$'        ;比较当前位是否结束
    JE eend               ;若是,转到eend
      AND AX,000fh        ;换成非压缩的BCD码,求得成绩
    MOV buffer2,AX        ;输入到分数小数位
    JMP ppoint        ;比较下一位

eend:                      ;结束时加和
    MOV AX,buffer1
    MUL n
    ADD AX,buffer2        ;整数部分加小数部分
        ADD sum_score,AX
        MOV buffer1,0        ;清空 buffer1和 buffer2
      MOV buffer2,0 

      RET
get_score ENDP
;----------------------------------------------------------------------
get_stand PROC NEAR
    PUSH AX        ;保护环境
    PUSH BX
          PUSH DX
    XOR AX,AX
    CLD

    MOV DX,[BX]    ;首先比较该成绩是否为100,由高位到低位按位比较
          AND DX,0F0FH    ;由ASC码转换成数值
    CMP DL, 01H    ;百位是否为1
        JNZ COMPARE    ;若否,转到COMPARE
    CMP DH, 0    ;若是,继续比较十位是否为0
    JNZ COMPARE    ;若否,转到COMPARE
    MOV DX,[BX+2]    ;若是,继续比较个位是否为0
          AND DX,0FH
    CMP DL, 0
    JNZ COMPARE    ;若否,转到COMPARE
    JMP COMPARE_90    ;若是,则表示成绩为100,转到COMPARE_90

COMPARE:        ;成绩不是100,直接比较十位即可
    MOV DX,[BX]
          AND DX,0F00H              
    CMP DH, 09H    ;比较该位数是否>=90
    JNC COMPARE_90    ;若是,转到COMPARE_90
    CMP DH, 08H    ;若否,继续比较是否>=80
    JNC COMPARE_80    ;若是,转到COMPARE_80
    CMP DH, 07H    ;若否,继续比较是否>=70
    JNC COMPARE_70    ;若是,转到COMPARE_70
    CMP DH, 06H    ;若否,继续比较是否>=60
    JNC COMPARE_60    ;若是,转到COMPARE_60
    XCHG AL, sco_60    ;若否,则<60分数段人数加1
    INC AL
    MOV sco_60, AL
      JMP DONE
COMPARE_60:        ;60-70分数段人数加1
    XCHG AL, sco_70
    INC AL
    MOV sco_70, AL
    JMP DONE
COMPARE_70:        ;70-80分数段人数加1
    XCHG AL, sco_80
    INC AL
    MOV sco_80, AL
    JMP DONE
COMPARE_80:        ;80-90分数段人数加1
    XCHG AL, sco_90
    INC AL
    MOV sco_90, AL
    JMP DONE
COMPARE_90:        ;90-100分数段人数加1
    XCHG AL, sco_100
    INC AL
    MOV sco_100, AL
    JMP DONE
DONE:    POP DX        ;恢复环境
          POP BX
    POP AX

    RET
get_stand ENDP
;----------------------------------------------------------------------
get_ave PROC NEAR        ;求平均数

    CALL lline        ;空行
    LEA AX,ave_mes         ;显示平均数
    MOV DX,AX
    MOV AH,09h
    INT 21h 
    CALL bblank        ;空格
    MOV AX,100
    MUL s_num
    CMP AX,sum_score    ;是否全部为满分
    JE ttt1            ;若是,转到ttt1
    MOV AX,sum_score
    XOR DI,DI        ;清空DI
    MOV DI,3
ttt2:
    XOR DX,DX        ;清空DX
    DIV n            ;AX除以权重10
    OR DL,30h
          DEC DI            
    MOV sscore[DI],DL    ;放入显示分数的字符串            
    CMP AX,0        ;判断AX是否比较完
    JE ttt3            ;若完成,转到ttt3
    JMP ttt2        ;否则继续比较下一位,由低位向高位
ttt3:
    MOV DL,sscore[DI]    ;按位显示,由高位到低位
    MOV AH,02h
    INT 21h
    CMP DI,1        ;当前位是否为个位
    JE dot            ;若是,显示小数点
    CMP DI,2        
    JE  dend
    INC DI
    JMP ttt3
dot:                ;显示小数点
    MOV DL,'.'
    INT 21h
    INC DI            ;显示一位小数
    JMP ttt3    
ttt1:                ;显示100分
    XOR DX,DX
    MOV DL,sscore
    MOV AH,09h
    INT 21h
dend:
    RET    
get_ave ENDP
;-------------------------------------------------------
lline PROC NEAR            ;空行
    LEA DX,line
    MOV AH,09h
    INT 21h ;
    RET
lline ENDP

bblank PROC NEAR        ;空格
    LEA DX,blank
    MOV AH,09h
    INT 21h ;
    RET
bblank ENDP

main ENDP
code ENDS
END start