+ -
当前位置:首页 → 问答吧 → 9号功能输出问题

9号功能输出问题

时间:2011-11-21

来源:互联网

本程序是从键盘输入学生姓名和成绩,按成绩升序排序,并显示结果

DATAS SEGMENT
  INFOR0 DB 0AH,0DH,'SORT=$'
  INFOR1 DB 0AH,0DH,'INPUT NAME:$'
  INFOR2 DB 0AH,0DH,'SCORE:$'
  N EQU 8 ;姓名长度
  M EQU 4 ;成绩长度(3位+回车符)
  P EQU 3 ;输入的人数
  Q EQU 3 ;成绩位数
  BUFF1 DB N,?,N DUP(0),'$'  
  BUFF2 DB M,?,M DUP(0),'$'
  SNAME DB P DUP(N+1 DUP(0)) ;保存姓名
  SCORE1 DW P DUP(M+1 DUP(0)) ;保存成绩
  SCORE2 DW P DUP(M+1 DUP(0))
  CIXU DB P DUP(0) ;输入次序
  X DW ?
  SIGN1 DW 0
  SIGN2 DW 0
  CONT DB '1'
DATAS ENDS

CODES SEGMENT
  ASSUME CS:CODES,DS:DATAS
   
MAIN PROC FAR  
START:

  MOV AX,DATAS
  MOV DS,AX
  MOV ES,AX
  MOV BX,0
  MOV CX,0
  CALL INPUT
  CALL SORT
  CALL PRINT
  MOV AH,4CH
  INT 21H  
   
  MOV AH,4CH
  INT 21H
   
MAIN ENDP 
;输入姓名成绩
INPUT PROC 

  INC BX
  CMP BX,P
  JA EXIT
  LEA DX,INFOR1
  MOV AH,9
  INT 21H
  LEA DX,BUFF1
  MOV AH,10
  INT 21H
  MOV AL,BUFF1+1 ;实际输入个数
  ADD AL,2 ;加2,包含buff1的0,1号单元
  MOV AH,0  
  MOV SI,AX  
  MOV BUFF1[SI],0 ;回车0d换为0,便于输出显示
   
  LEA DX,INFOR2
  MOV AH,9
  INT 21H
   
  MOV AL,BUFF2+1
  ADD AL,2
  MOV AH,0
  MOV SI,AX
  MOV BUFF2[SI],0  
   
  MOV CIXU[BX-1],BL
   
  CMP BX,1
  JZ LET1
  ADD SIGN1,N+1
  ADD SIGN2,Q
  LET1:
  CALL COPY
  JMP INPUT
  EXIT:
  RET
INPUT ENDP 
;数据转存
COPY PROC
   
  MOV CX,N+1
  LEA SI,BUFF1+2
  LEA DI,SNAME
  ADD DI,SIGN1
  CLD
  REP MOVSB
  MOV CX,N
  MOV AX,'$'
  LEA DI,BUFF1+2
  REP STOSB
  MOV CX,M+1
  LEA SI,BUFF2+2
  LEA DI,SCORE1
  ADD DI,SIGN2
  CLD
  REP MOVSB
  LEA SI,BUFF2+2
  MOV DI,SIGN2
  CALL CHANGE
  RET
COPY ENDP
;十进制数ASCII→二进制
CHANGE PROC
  MOV X,0
  MOV CX,[SI-1]
  AND CX,000FH
  REPT2: 
  MOV AL,[SI]
  CMP AL,30H
  JL EXIT1
  CMP AL,39H
  JG EXIT1
  AND AX,000FH
  XCHG AX,X
  MOV DX,10
  MUL DX
  ADD X,AX
  INC SI
  LOOP REPT2
  MOV AX,X
  MOV SCORE2[DI],AX
  MOV X,0
  ADD SIGN2,2
  EXIT1:RET
CHANGE ENDP
;排序
SORT PROC

  MOV CX,P
  DEC CX
  LOOP1:PUSH CX
  MOV BX,0
  MOV SI,0
  LOOP2:MOV AX,SCORE2[BX]
  CMP AX,SCORE2[BX+M+1]
  JGE NEXT
  XCHG AX,SCORE2[BX+M+1]
  MOV SCORE2[BX],AX
  MOV AL,CIXU[SI]
  XCHG AL,CIXU[SI+1]
  MOV CIXU[SI],AL
  NEXT:ADD BX,M+1
  INC SI
  LOOP LOOP2
  POP CX
  LOOP LOOP1
  RET
SORT ENDP
;输出
PRINT PROC 
   
  LEA DX,INFOR0
  MOV AH,9
  INT 21H
  MOV CX,P
  MOV BX,0
  MOV AX,0
  MOV DI,0
  REPT3:
  MOV DL,0AH
  MOV AH,2
  INT 21H
  MOV DL,0DH
  INT 21H
  MOV DL,CONT
  MOV AH,2
  INT 21H
  INC CONT
  MOV DL,0AH
  MOV AH,2
  INT 21H
  MOV DL,0DH
  INT 21H
  MOV AX,0
  MOV AL,CIXU[DI]
  DEC AL
  MOV BL,9
  MUL BL
  LEA DX,SNAME
  ADD DX,AX
  MOV AH,9
  INT 21H
  MOV DL,0AH
  MOV AH,2
  INT 21H
  MOV DL,0DH
  MOV AH,2
  INT 21H
  MOV AX,0
  MOV BX,0
  MOV AL,CIXU[DI]
  DEC AL
  MOV BL,5
  MUL BL
  LEA DX,SCORE1 
  ADD DX,AX
  MOV AH,9
  INT 21H
  INC DI
  LOOP REPT3
  RET
PRINT ENDP  
   
CODES ENDS
  END START


为什么这里将回车换成0会便于输出呢。为什么它能正确输出呢?用9号功能不是碰到$符号是结束吗。而这个程序似乎是为每一个姓名或成绩分配了一个固定长度的缓冲区,$符号是放在最后面的。如果输入的姓名没有达到固定长度时就会有空余字符,按理说是会输出乱码的,但它却正常输出了,费解!
这是一个郑晓薇《汇编语言》的一个程序,有看懂的能解释一下么

作者: ncist_jianeng   发布时间: 2011-11-21

乱码,0 字节不会乱码吧,显示的是空白而已,所以,即便是不足长度,也是看不出来的。

作者: zara   发布时间: 2011-11-21

引用楼主 ncist_jianeng 的回复:
本程序是从键盘输入学生姓名和成绩,按成绩升序排序,并显示结果

DATAS SEGMENT
INFOR0 DB 0AH,0DH,'SORT=$'
INFOR1 DB 0AH,0DH,'INPUT NAME:$'
INFOR2 DB 0AH,0DH,'SCORE:$'
N EQU 8 ;姓名长度
M EQU 4 ;成绩长度(3位+回车符)
P EQU 3 ;输……

Assembly code

;本程序是从键盘输入学生姓名和成绩,按成绩升序排序,并显示结果

DATAS SEGMENT
    INFOR0 DB 0AH,0DH,'SORT=$'
    INFOR1 DB 0AH,0DH,'INPUT NAME:$'
    INFOR2 DB 0AH,0DH,'SCORE:$'
    
    N EQU 8 ;姓名长度
    M EQU 4 ;成绩长度(3位+回车符)
    P EQU 3 ;输入的人数
    Q EQU 3 ;成绩位数
    
    BUFF1 DB N,?,N DUP(0),'$'   
    BUFF2 DB M,?,M DUP(0),'$'
    
    SNAME DB P DUP(N+1 DUP(0))  ;保存姓名
    SCORE1 DW P DUP(M+1 DUP(0)) ;保存成绩
    SCORE2 DW P DUP(M+1 DUP(0))
    CIXU DB P DUP(0) ;输入次序
    X DW ?
    SIGN1 DW 0
    SIGN2 DW 0
    CONT DB '1'
DATAS ENDS

CODES SEGMENT
        ASSUME CS:CODES,DS:DATAS
MAIN PROC FAR   
START:
        MOV AX,DATAS
        MOV DS,AX
        MOV ES,AX
        
        MOV BX,0
        MOV CX,0
        CALL INPUT
        CALL SORT
        CALL PRINT
        MOV AH,4CH
        INT 21H   
    
        MOV AH,4CH
        INT 21H
MAIN ENDP 
;---------------------------------------------------------------------
;输入姓名成绩
;---------------------------------------------------------------------
INPUT PROC  
        INC BX
        CMP BX,P        ;到达输入的最大人数了吗
        JA EXIT         ;超过了,退出
        
        LEA DX,INFOR1   ;显示提示信息
        MOV AH,9
        INT 21H
        
        LEA DX,BUFF1    ;接收BUFF1
        MOV AH,10
        INT 21H
        
        MOV AL,BUFF1+1      ;实际输入个数
        ADD AL,2            ;加2,包含buff1的0,1号单元
        MOV AH,0   
        MOV SI,AX            
        MOV BUFF1[SI],0      ;回车0d换为0,便于输出显示
    
        LEA DX,INFOR2        ;显示提示信息
        MOV AH,9
        INT 21H
        ;----------------
        ;这里得进输入串的功能
        LEA DX,BUFF2    ;接收BUFF2
        MOV AH,10
        INT 21H
        ;--------------------
        MOV AL,BUFF2+1      ;实际输入的字符数
        ADD AL,2            ;追回2个字节
        MOV AH,0
        MOV SI,AX
        MOV BUFF2[SI],0     ;换为0
    
        MOV CIXU[BX-1],BL   ;BX初值为3
        CMP BX,1
        JZ LET1             ;第一次不需要设置了,跳出
            ADD SIGN1,N +1  ;姓名长度
            ADD SIGN2,Q     ;成绩位数
        LET1:
        CALL COPY
        JMP INPUT
EXIT:
        RET
INPUT ENDP  
;---------------------------------------------------------------------
;数据转存
;---------------------------------------------------------------------
COPY PROC
    
        MOV CX,N+1          ;姓名长度+1(连最后的'$'也包括进来了)
        LEA SI,BUFF1+2      ;
        LEA DI,SNAME        ;目标缓冲区
        ADD DI,SIGN1        ;调整接收位置
        CLD
        REP MOVSB           ;复制姓名
        
        MOV CX,N
        MOV AX,'$'
        LEA DI,BUFF1+2
        REP STOSB           ;将串BUFF1+2置'$'
        
;有了上面两处的置'$',所以用dos 中断9号功能显示是可行的。
        
        MOV CX,M+1
        LEA SI,BUFF2+2
        LEA DI,SCORE1
        ADD DI,SIGN2
        CLD
        REP MOVSB            ;复制成绩
        
        LEA SI,BUFF2+2
        MOV DI,SIGN2
        CALL CHANGE          ;将成绩转换成二进制
        RET
COPY ENDP
;---------------------------------------------------------------------
;十进制数ASCII→二进制
;---------------------------------------------------------------------
CHANGE PROC
        MOV X,0
        MOV CX,[SI-1]   ;实际字符数
        AND CX,000FH    ;实际字符数
REPT2:  
        MOV AL,[SI]
        CMP AL,30H
        JL EXIT1
        CMP AL,39H
        JG EXIT1
        AND AX,000FH
        XCHG AX,X        ;X保存上次的积
        MOV DX,10
        MUL DX
        ADD X,AX         ;X保存上次的积
        
        INC SI
        LOOP REPT2
        
        MOV AX,X
        MOV SCORE2[DI],AX
        MOV X,0
        ADD SIGN2,2
EXIT1:    RET
CHANGE ENDP
;---------------------------------------------------------------------
;排序
;---------------------------------------------------------------------
SORT PROC
        MOV CX,P
        DEC CX        ;最大人数-1
LOOP1:
        PUSH CX
        MOV BX,0
        MOV SI,0
LOOP2:
        MOV AX,SCORE2[BX]
        CMP AX,SCORE2[BX+M+1]
        JGE NEXT
            ;交换成绩
            XCHG AX,SCORE2[BX+M+1]
            MOV SCORE2[BX],AX
            
            ;交换名次
            MOV AL,CIXU[SI]
            XCHG AL,CIXU[SI+1]
            MOV CIXU[SI],AL
        NEXT:
        ADD BX,M+1    ;指向下一成绩
        INC SI        ;指向下一名次
        LOOP LOOP2
        
        POP CX
        LOOP LOOP1 ;--CX , 如果cx!=0 再循环
                   ;(算法不科学,如果输入就是排好序的,
                   ;那不是也要循环cx次?)
        RET
SORT ENDP
;---------------------------------------------------------------------
;输出
;---------------------------------------------------------------------
PRINT PROC  
        LEA DX,INFOR0
        MOV AH,9
        INT 21H
        
        MOV CX,P
        MOV BX,0
        MOV AX,0
        MOV DI,0
REPT3:
        ;回车换行
        MOV DL,0AH
        MOV AH,2
        INT 21H
        MOV DL,0DH
        INT 21H
        
        ;显示count
        MOV DL,CONT ;(如果人数多于9个什么显示什么?)
        MOV AH,2
        INT 21H
        INC CONT  ;(如果人数多于9个什么显示什么?)
        
        ;回车换行
        MOV DL,0AH
        MOV AH,2
        INT 21H
        MOV DL,0DH
        INT 21H
        
        MOV AX,0
        MOV AL,CIXU[DI]
        DEC AL
        MOV BL,9    ;姓名域尺寸
        MUL BL    
        
        LEA DX,SNAME
        ADD DX,AX
        MOV AH,9
        INT 21H
        
        ;换行回车(应该0Dh在前)
        MOV DL,0AH
        MOV AH,2
        INT 21H
        MOV DL,0DH
        MOV AH,2
        INT 21H
        
        MOV AX,0
        MOV BX,0
        MOV AL,CIXU[DI]
        DEC AL
        MOV BL,5 ;成绩域尺寸
        MUL BL
        
        LEA DX,SCORE1
        ADD DX,AX
        MOV AH,9
        INT 21H
        INC DI
        LOOP REPT3
        RET
PRINT ENDP   
    
CODES ENDS
        END MAIN    ;START

作者: gsy999   发布时间: 2011-11-21