www.pudn.com > DOS保护模式下汇编程序设计.zip > PMPRINT.ASM


;                Protected-Mode Screen Management Procedures. 
; 
; 
;   DS assumed to be set to flat-model data selector.  Screen address assumed at 
;B8000H.  Cursor position address assumed at 450H. 
;   A full explanation of each procedure is provided above the procedure.  The 
;following is a brief summary of all included procedures: 
; 
;Procedure     Description 
;PCH           Print ASCII character in AL at cursor 
;CRLF          Issue carriage return and line feed 
;SCRLUP        Scoll screen up 
;SPC           Print AL spaces at cursor 
;GETCSR        Get cursor position in AX.  AH = row, AL = column 
;SETCSR        Set cursor position at (row,col) = (AH,AL) 
;CLS           Clear screen 
;PSTR          Print zero terminated ASCII string at ES:EBX 
;PCSSTR        Print zero terminated ASCII string at CS:EBX 
;PHW           Print hexadecimal WORD in AX 
;PHD           Print hexadecimal DWORD in EAX 
;PUW           Print unsigned WORD in AX as decimal 
;PUD           Print unsigned DWORD in EAX as decimal 
;PSW           Print signed WORD in AX as decimal 
;PSD           Print signed DWORD in EAX as decimal 
;FPST          Print ST of FPU using format in AX.  AH = characters to left of 
;              decimal.  AL = characters to right of decimal. 
 
SCRNBASEADR    EQU            000B8000H 
CURPOS         EQU            00000450H 
 
;Print ASCII code in AL at cursor. 
PCH            PROC NEAR 
               PUSH           EBX 
               PUSH           EDX 
               MOV            EDX,DWORD PTR DS:[CURPOS]     ;Cursor (row,col) in (DH,DL) 
               PUSH           EDX                           ;Push cursor position 
               XOR            EBX,EBX 
               MOV            BL,DH                         ;Multiply row by 160 
               SHL            BL,2 
               ADD            BL,DH 
               SHL            EBX,5 
               AND            EDX,0FFH                      ;Clear all but column 
               ADD            DL,DL                         ;Multiply column by 2 
               ADD            EBX,EDX 
               ADD            EBX,SCRNBASEADR 
               POP            EDX                           ;POP cursor position 
               MOV            [EBX],AL 
               INC            DL                            ;Increment column 
               CMP            DL,79 
               JBE            RCDCURSOR 
               XOR            DL,DL                         ;Move to zero column of next row 
               INC            DH                            ;Move to next row 
RCDCURSOR:     MOV            WORD PTR DS:[CURPOS],DX       ;Assume row is valid 
               CMP            DH,24 
               JA             DOSCROLL 
EXIT:          POP            EDX 
               POP            EBX 
               RET 
DOSCROLL:      CALL           SCRLUP 
               JMP            EXIT 
PCH            ENDP 
 
;Clear cursor to end of line and issue CRLF.  Scroll up if necessary. 
CRLF           PROC NEAR 
               PUSH           EAX 
               PUSH           EBX 
               PUSH           ECX 
               MOV            EAX,DWORD PTR DS:[CURPOS] 
               PUSH           EAX                           ;PUSH cursor position 
               XOR            EBX,EBX 
               MOV            BL,AH                         ;Multiply row by 160 
               SHL            BL,2 
               ADD            BL,AH 
               SHL            EBX,5 
               AND            EAX,0FFH                      ;Clear all but column 
               MOV            CL,80 
               SUB            CL,AL                         ;Get number of bytes to clear in CL 
               ADD            AL,AL                         ;Multiply column by 2 
               ADD            EBX,EAX 
               ADD            EBX,SCRNBASEADR 
               MOV            AL,32 
CLREOL:        MOV            [EBX],AL                      ;Clear to end of line 
               ADD            EBX,2 
               DEC            CL 
               JNZ            CLREOL 
               POP            EAX                           ;POP cursor position 
               INC            AH                            ;Increment row 
               CMP            AH,24 
               JA             DOSCROLL 
               XOR            AL,AL                         ;Set column to zero 
               MOV            WORD PTR DS:[CURPOS],AX 
EXIT:          POP            ECX 
               POP            EBX 
               POP            EAX 
               RET 
DOSCROLL:      CALL           SCRLUP 
               JMP            EXIT 
CRLF           ENDP 
 
;Scroll entire screen up one line and leave cursor at start of line 24. 
SCRLUP         PROC NEAR 
               PUSH           EAX 
               PUSH           EBX 
               PUSH           ECX 
               MOV            EBX,SCRNBASEADR 
               MOV            ECX,960                       ;960 = (80*24*2)/4 (DWORDS to scroll) 
SCROLLLOOP:    MOV            EAX,[EBX+160] 
               MOV            [EBX],EAX 
               ADD            EBX,4 
               DEC            ECX 
               JNZ            SCROLLLOOP 
               MOV            CL,80 
               MOV            AL,32 
CLR24:         MOV            [EBX],AL                      ;Clear line 24 
               ADD            EBX,2 
               DEC            CL 
               JNZ            CLR24 
EXIT:          MOV            WORD PTR DS:[CURPOS],1800H    ;Set cursor to bottom line in zero column 
               POP            ECX 
               POP            EBX 
               POP            EAX 
               RET 
SCRLUP         ENDP 
 
;Print AL spaces at cursor. 
SPC            PROC NEAR 
               OR             AL,AL 
               JZ             EXIT 
               PUSH           EAX 
               MOV            AH,AL 
               MOV            AL,32 
PRINTSPC:      CALL           PCH 
               DEC            AH 
               JNZ            PRINTSPC 
               POP            EAX 
EXIT:          RET 
SPC            ENDP 
 
;Set cursor location at (row,col) = (AH,AL). 
SETCSR         PROC NEAR 
               CMP            AH,24                         ;Do not allow row greater than 24 
               JBE            CHKCOL 
               MOV            AH,24 
CHKCOL:        CMP            AL,79                         ;Do not allow column greater than 79 
               JBE            SETCURSOR 
               MOV            AL,79 
SETCURSOR:     MOV            WORD PTR DS:[CURPOS],AX 
               RET 
SETCSR         ENDP 
 
;Get cursor position in AX. 
GETCSR         PROC NEAR 
               MOV            AX,WORD PTR DS:[CURPOS] 
               RET 
GETCSR         ENDP 
 
;Clear screen and leave cursor at (0,0) position. 
CLS            PROC NEAR 
               PUSH           EAX 
               PUSH           EBX 
               PUSH           ESI 
               MOV            EBX,SCRNBASEADR 
               MOV            ESI,1999 
               MOV            AL,32 
DOCLS:         MOV            [EBX+2*ESI],AL 
               DEC            ESI 
               JNS            DOCLS 
               MOV            WORD PTR DS:[CURPOS],0H 
               POP            ESI 
               POP            EBX 
               POP            EAX 
               RET 
CLS            ENDP 
 
;Print ASCIIZ string at address in ES:EBX. 
PSTR           PROC NEAR 
               PUSH           EAX 
               PUSH           EBX 
CHARLOOP:      MOV            AL,ES:[EBX] 
               OR             AL,AL                         ;See if at end of string 
               JZ             EXIT 
               CALL           PCH 
               INC            EBX 
               JMP            CHARLOOP 
EXIT:          POP            EBX 
               POP            EAX 
               RET 
PSTR           ENDP 
 
;Print ASCIIZ string at address CS:EBX. 
PCSSTR         PROC NEAR 
               PUSH           EAX 
               PUSH           EBX 
CHARLOOP:      MOV            AL,CS:[EBX]                   ;See if at end of string 
               OR             AL,AL 
               JZ             EXIT 
               CALL           PCH 
               INC            EBX 
               JMP            CHARLOOP 
EXIT:          POP            EBX 
               POP            EAX 
               RET 
PCSSTR         ENDP 
 
;Print hexadecimal WORD in AX. 
PHW            PROC NEAR 
               PUSH           EAX 
               PUSH           ECX 
               PUSH           EDX 
               MOV            EDX,EAX 
               MOV            CL,4                          ;Print four nibbles 
CALCNIBS:      MOV            AL,DL 
               AND            AL,0FH 
               ADD            AL,48 
               CMP            AL,57 
               JBE            PUSHDIGIT 
               ADD            AL,7 
PUSHDIGIT:     PUSH           EAX 
               SHR            EDX,4 
               DEC            CL 
               JNZ            CALCNIBS 
               MOV            CL,4 
PRNTNIBS:      POP            EAX 
               CALL           PCH 
               DEC            CL 
               JNZ            PRNTNIBS 
               POP            EDX 
               POP            ECX 
               POP            EAX 
               RET 
PHW            ENDP 
 
;Print hexadecimal DWORD in EAX. 
PHD            PROC NEAR 
               PUSH           EAX 
               PUSH           ECX 
               PUSH           EDX 
               MOV            EDX,EAX 
               MOV            CL,8                          ;Print eight nibbles 
CALCNIBS:      MOV            AL,DL 
               AND            AL,0FH 
               ADD            AL,48 
               CMP            AL,57 
               JBE            PUSHDIGIT 
               ADD            AL,7 
PUSHDIGIT:     PUSH           EAX 
               SHR            EDX,4 
               DEC            CL 
               JNZ            CALCNIBS 
               MOV            CL,8 
PRNTNIBS:      POP            EAX 
               CALL           PCH 
               DEC            CL 
               JNZ            PRNTNIBS 
               POP            EDX 
               POP            ECX 
               POP            EAX 
               RET 
PHD            ENDP 
 
;Print unsigned WORD in AX as decimal. 
PUW            PROC NEAR 
               PUSH           EAX 
               PUSH           EBX 
               PUSH           ECX 
               PUSH           EDX 
               AND            EAX,0FFFFH 
               XOR            CL,CL 
               MOV            EBX,10 
CALCDIGS:      XOR            EDX,EDX 
               DIV            BX 
               PUSH           EDX 
               INC            CL 
               OR             EAX,EAX 
               JNZ            CALCDIGS 
PRNTDIGS:      POP            EAX 
               ADD            AL,48 
               CALL           PCH 
               DEC            CL 
               JNZ            PRNTDIGS 
               POP            EDX 
               POP            ECX 
               POP            EBX 
               POP            EAX 
               RET 
PUW            ENDP 
 
;Print unsigned DWORD in EAX as decimal. 
PUD            PROC NEAR 
               PUSH           EAX 
               PUSH           EBX 
               PUSH           ECX 
               PUSH           EDX 
               XOR            CL,CL 
               MOV            EBX,10 
CALCDIGS:      XOR            EDX,EDX 
               DIV            EBX 
               PUSH           EDX 
               INC            CL 
               OR             EAX,EAX 
               JNZ            CALCDIGS 
PRNTDIGS:      POP            EAX 
               ADD            AL,48 
               CALL           PCH 
               DEC            CL 
               JNZ            PRNTDIGS 
               POP            EDX 
               POP            ECX 
               POP            EBX 
               POP            EAX 
               RET 
PUD            ENDP 
 
;Print signed WORD in AX as decimal. 
PSW            PROC NEAR 
               PUSH           EAX 
               OR             AX,AX 
               JNS            PABS 
               PUSH           EAX 
               MOV            AL,"-" 
               CALL           PCH 
               POP            EAX 
               NEG            AX                            ;Calculate absolute value 
PABS:          CALL           PUW                           ;Print absolute value 
               POP            EAX 
               RET 
PSW            ENDP 
 
;Print signed DWORD in EAX as decimal. 
PSD            PROC NEAR 
               PUSH           EAX 
               OR             EAX,EAX 
               JNS            PABS 
               PUSH           EAX 
               MOV            AL,"-" 
               CALL           PCH 
               POP            EAX 
               NEG            EAX                           ;Calculate absolute value 
PABS:          CALL           PUD                           ;Print absolute value 
               POP            EAX 
               RET 
PSD            ENDP 
 
;Print ST of FPU using format code in AX.  AH = number of postdecimal characters 
;including sign (if negative).  AL = number of predecimal characters.  Fractions 
;are printed with leading zero provided that AH > 0.  Can print numbers 
;absolutely smaller than 10 ^ 18.  Can print up to 18 predecimal places.  Will 
;fill entire print field with "*" if postdecimal field is too small.  Will fill 
;entire print field with ">" if number absolutely greater than 10 ^ 18. 
FPST           PROC NEAR PUBLIC 
               LOCAL NOHIDIGITS:DWORD 
               LOCAL NOLODIGITS:DWORD 
               LOCAL OLDCWORD:WORD 
               LOCAL NEWCWORD:WORD 
               LOCAL HIDIGITS[10]:BYTE 
               LOCAL LODIGITS[10]:BYTE 
               PUSH           EAX 
               PUSH           ECX 
               PUSH           EDX 
               PUSH           ESI 
               PUSH           EDI 
               XOR            ECX,ECX                       ;Save format codes 
               MOV            CL,AL 
               MOV            NOLODIGITS,ECX 
               MOV            CL,AH 
               MOV            NOHIDIGITS,ECX 
               FLD            ST                            ;See if number of high digits greater than 18 
               FABS 
               FCOM           QWORD PTR CS:SCALEFAC 
               FSTSW          AX 
               SAHF 
               JAE            OVERFLOW 
               FSTCW          OLDCWORD                      ;Set RC to truncate 
               MOV            AX,OLDCWORD 
               OR             AX,0C00H 
               MOV            NEWCWORD,AX 
               FLDCW          NEWCWORD 
               FLD            ST(1)                         ;Save high digits 
               FBSTP          TBYTE PTR HIDIGITS[0] 
               FLD            ST                            ;Calculate and save low digits 
               FRNDINT 
               FLDCW          OLDCWORD 
               FSUB 
               FMUL           QWORD PTR CS:SCALEFAC 
               XOR            AL,AL 
               XOR            EDI,EDI 
               MOV            ESI,8 
               FBSTP          TBYTE PTR LODIGITS[0] 
GETHIDIGIT:    IF (@WordSize EQ 4) 
               OR             AL,HIDIGITS[ESI]              ;Find first nonzero digit 
               ELSE 
               OR             AL,HIDIGITS[SI] 
               ENDIF 
               JNZ            CALCHIORDER 
               DEC            ESI 
               JNS            GETHIDIGIT 
               XOR            ESI,ESI                       ;There are no nonzero high digits 
               OR             CL,CL                         ;See if a leading zero can be added to fraction 
               JZ             CHKSIGN 
               INC            ESI                           ;Add leading zero 
               JMP            CHKSIGN 
CALCHIORDER:   MOV            EDI,ESI 
               INC            ESI                           ;Convert ESI to number of high digits 
               ADD            ESI,ESI 
               AND            AL,0F0H                       ;See if highest digit is in odd position 
               JNZ            CHKSIGN 
               DEC            ESI 
CHKSIGN:       MOV            DL,HIDIGITS[9]                ;Get sign byte 
               OR             DL,DL 
               JNS            CALCSPACES 
               INC            ESI                           ;Account for "-" 
CALCSPACES:    SUB            ECX,ESI                       ;Calculate number of leading spaces 
               JB             SMALLFLD 
               JE             PRNTSIGN 
               MOV            AL," " 
PRNTSPACES:    CALL           PCH 
               DEC            ECX 
               JNZ            PRNTSPACES 
PRNTSIGN:      OR             DL,DL 
               JNS            PRNTHIDIGITS 
               MOV            AL,"-" 
               CALL           PCH 
               DEC            ESI 
               JZ             PRNTDEC 
PRNTHIDIGITS:  IF (@WordSize EQ 4) 
               MOV            DL,HIDIGITS[EDI] 
               ELSE 
               MOV            DL,HIDIGITS[DI] 
               ENDIF 
               TEST           ESI,01H 
               JNZ            ODDDIGIT 
HIDIGITLOOP:   MOV            AL,DL 
               SHR            AL,4 
               ADD            AL,48 
               CALL           PCH 
ODDDIGIT:      MOV            AL,DL 
               AND            AL,0FH 
               ADD            AL,48 
               CALL           PCH 
               DEC            EDI 
               JS             PRNTDEC 
               IF (@WordSize EQ 4) 
               MOV            DL,HIDIGITS[EDI] 
               ELSE 
               MOV            DL,HIDIGITS[DI] 
               ENDIF 
               JMP            HIDIGITLOOP 
PRNTDEC:       MOV            ECX,NOLODIGITS 
               OR             ECX,ECX 
               JZ             EXIT 
               MOV            AL,"." 
               CALL           PCH 
               MOV            EDI,8 
LODIGITLOOP:   IF (@WordSize EQ 4) 
               MOV            DL,LODIGITS[EDI] 
               ELSE 
               MOV            DL,LODIGITS[DI] 
               ENDIF 
               MOV            AL,DL 
               SHR            AL,4 
               ADD            AL,48 
               CALL           PCH 
               DEC            ECX 
               JZ             EXIT 
               MOV            AL,DL 
               AND            AL,0FH 
               ADD            AL,48 
               CALL           PCH 
               DEC            ECX 
               JZ             EXIT 
               DEC            EDI 
               JNS            LODIGITLOOP 
EXIT:          POP            EDI 
               POP            ESI 
               POP            EDX 
               POP            ECX 
               POP            EAX 
               RET 
FILLFLD:       MOV            ECX,NOLODIGITS 
               OR             ECX,ECX 
               JNZ            CALCNOCHARS 
               INC            ECX 
CALCNOCHARS:   ADD            ECX,NOHIDIGITS 
PRNTCHAR:      CALL           PCH 
               DEC            ECX 
               JNZ            PRNTCHAR 
               JMP            EXIT 
SMALLFLD:      MOV            AL,"*" 
               JMP            FILLFLD 
OVERFLOW:      FSTP           ST                            ;Pop absolute value of number 
               MOV            AL,">" 
               JMP            FILLFLD 
               ALIGN          4 
SCALEFAC: 
               DQ             43ABC16D674EC800H             ;10 ^ 18 
FPST           ENDP