Category : Assembly Language Source Code
Archive   : XLIB20.ZIP
Filename : PMPRINT.ASM

 
Output of file : PMPRINT.ASM contained in archive : XLIB20.ZIP

; 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