📄 tskprf.asm
字号:
;
; --- Version 2.2 93-03-03 17:17 ---
;
; CTask - Printf replacement
;
; Public Domain Software written by
; Thomas Wagner
; Ferrari electronic Gmbh
; Beusselstrasse 27
; D-1000 Berlin 21
; Germany
;
; This file is new with Version 2.1.
;
; This module contains substitutes for the standard C printf
; family formatting routines. It uses no helper routines, and
; thus can be called from Assembler programs and is model
; independent. It is smaller and faster (up to 5 times) than
; the standard C printf, and supports all output options except
; floating point and some esoteric flags.
;
; Also supported is output to the second monitor in a dual-
; monitor system.
;
; The routines in this module are reentrant in the sense that nothing
; will crash if routines are re-entered concurrently. No protection
; against a garbled screen is built in, however, so external
; resource request/release calls are still necessary to make
; sure output to the display stays in proper order. The sprintf
; routines need no protection.
;
; No CTask specific stuff is used to allow use of the routines
; even when CTask is not installed.
;
; Note that the tsk_fprintf routine takes a different parameter
; than the standard fprintf. You have to pass an integer file
; handle, not a FILE *.
;
;---------------------------------------------------------------------------
;
; Conversion format:
;
; % [flags] [width] [.precision] [indirection] [size] conversion
;
; Flags supported:
;
; - Left-justify output
;
; the +, blank, and # flags are not supported.
;
; Width and precision are handled like in standard C, i.e.
; the * specification is supported. The only exception is
; that numeric output will not be suppressed for an explicit
; 0 precision.
;
; Size modifiers supported:
;
; N Near pointer
; F Far pointer
; h Short
; l Long
; H Byte-sized operand in parameter list
;
; Conversion characters supported:
;
; c single character
; s zero-terminated string
; x unsigned hex word, a-f
; X unsigned hex word, A-F
; d signed decimal int
; u unsigned decimal int
; p hex pointer, a-f
; P hex pointer, A-F
; n store converted length at int pointer
;
; In addition, two indirection operators are supported. Both
; can be repeated, but they should not normally be mixed.
;
; ^ Near indirection (param is DS-based near pointer)
; @ Far indirection (param is far pointer)
;
; Example:
; %d Displays the word parameter
; %^d Displays the word at DS:parameter
; %@d Displays the word at the far address
; given as parameter
;
;---------------------------------------------------------------------------
;
name tskprf
;
include tsk.mac
;
.tsk_model
;
public tsk_regen ; far pointer to regen buffer
public tsk_regen_s ; regen buffer segment
public tsk_regen_o ; current regen buffer offset
public tsk_disport ; display controller I/O port
public tsk_comport ; comm I/O port
;
Pubfunc tsk_putc ; put char to screen
Pubfunc tsk_puts ; put string to screen
Pubfunc tsk_rputc ; put char to regen
Pubfunc tsk_rputs ; put string to regen
Pubfunc tsk_cputc ; put char to comm port
Pubfunc tsk_cputs ; put string to comm port
;
CPubfnc tsk_printf ; print to screen
Pubfunc tsk_vprintf ; print to screen with arg pointer
CPubfnc tsk_fprintf ; print to file handle
Pubfunc tsk_vfprintf ; print to file handle w. argptr
CPubfnc tsk_sprintf ; print to string
Pubfunc tsk_vsprintf ; print to string w. argptr
CPubfnc tsk_rprintf ; print to regen
Pubfunc tsk_vrprintf ; print to regen w. argptr
CPubfnc tsk_cprintf ; print to comm port
Pubfunc tsk_vcprintf ; print to comm port w. argptr
;
Pubfunc tsk_setpos ; set regen cursor position
Pubfunc tsk_set_regen ; set regen address
Pubfunc tsk_set_dualdis ; init secondary monitor
Pubfunc tsk_set_currdis ; init primary monitor
Pubfunc tsk_set_colour ; init colour monitor
Pubfunc tsk_set_mono ; init mono monitor
Pubfunc tsk_set_attr ; set display attribute
Pubfunc tsk_set_clreol ; CR clears to EOL when set
;
Pubfunc tsk_cprint_init ; init comm port
Pubfunc tsk_cprint_getc ; get comm port char (no wait)
Pubfunc tsk_cprint_waitc ; get comm port char (with wait)
;
;
; Configuration options:
;
; FILE_BUFSIZE Is the local buffer size for tsk_fprintf and tsk_vfprintf.
; The buffer is allocated on the stack, so it should
; not be chosen too large to avoid stack overflows.
; It must be a power of 2, and less than or equal to 256.
;
FILE_BUFSIZE = 64 - 1
;
;
; DFLT_FAR If set, pointers (%p and %n) and strings (%s) are assumed
; far by default, near pointers must use the N size
; modifiers.
; If clear, the default is near, so the F size modifier
; must be used for far pointers.
;
DFLT_FAR = 1 ; by default, pointers and strings are Far
;
;
; The local variables used in the main formatter.
; Those variables are relative to BP, and are accessed by
; several routines in this module (the local routines do not
; use the standard stack discipline, they should be viewed as
; Pascal-like nested routines within the scope of @disprintf).
;
dislocrec struc
convbuf db 17 dup(?) ; conversion buffer (hex/dec)
prflags db ? ; formatting flags
prhexch db ? ; Hex format offset for upper/lower case
prfcnt db ? ; file output counter
procnt dw ? ; output char counter
prwidth dw ? ; field width
prec dw ? ; precision
arglen dw ? ; argument length in bytes
prproc dw ? ; output routine offset
prargbx dw ? ; output routine BX argument
prargdx dw ? ; output routine DX argument
dislocrec ends
;
; formatting flags
;
F_LONGARG = 01h ; argument is long/far (4 bytes)
F_SHORTARG = 02h ; argument is single byte
F_PADZERO = 04h ; pad with zeros
F_LEFTADJ = 08h ; left adjust output
F_SIGNED = 10h ; signed number
F_WIDTH = 20h ; width is valid
F_PREC = 40h ; precision is valid
F_INDIR = 80h ; indirection was used
;
XON = 11h
XOFF = 13h
;
biosdata segment at 40h
org 4ah
bios_cols dw ?
org 63h
bios_chipad dw ?
org 84h
bios_rows db ?
biosdata ends
;
.tsk_data
;
tsk_regen label dword
tsk_regen_o dw 0
tsk_regen_s dw 0b000h ; default mono screen
;
tsk_disport dw 3b4h ; default mono 6845
tsk_attrib db 07h ; default white on black
;
sc_clreol db 0 ; default is don't clear
;
sc_cols dw 80 * 2
sc_end dw 25 * 80 * 2
;
tsk_comport dw 0
tsk_combuf db 16 dup(0)
tsk_comiptr dw 0
tsk_comoptr dw 0
tsk_comcnt dw 0
tsk_comxoff db XON
;
sc_proc dw offset @nodis
;
.tsk_edata
.tsk_code
;
ctdataseg dw @CTASK_DATA
;
; setcsr - local routine to set the cursor to the current position
; on the regen display.
;
@setcsr proc near
;
push dx
mov dx,tsk_disport
or dx,dx
jz no_cursor
mov al,0eh
out dx,al
jmp $+2
mov ax,tsk_regen_o
shr ax,1
xchg ah,al
inc dx
out dx,al
jmp $+2
dec dx
mov al,0fh
out dx,al
jmp $+2
mov al,ah
inc dx
out dx,al
;
no_cursor:
pop dx
ret
;
@setcsr endp
;
;
; disregen - local routine to write char directly into the display
; regen buffer. The following control characters
; are handled special:
; 08 \b (BS) backspace one position (no erase)
; 09 \t (TAB) tab to next 8th column
; 0D \r (CR) carriage return
; 0A \n (LF) line feed
; Note: the printf routines will not pass
; a single line feed unchanged.
; 0B \v (VT) clear to end of line
; 0C \f (FF) clear to end of screen
;
;
; Entry: AL = char to display
; Uses: AX
;
@disregen proc near
;
push ds
mov ds,cs:ctdataseg ; allow access to local vars
;
; First, check for control characters
;
cmp al,0eh ; 08-0D are special
jae no_special
cmp al,08h
jb no_special
je dis_bs ; 08 = Backspace
cmp al,0ah
jb dis_tab ; 09 = Tab
je dis_lf ; 0A = Linefeed
cmp al,0ch
jb dis_vt ; 0B = Clear to eol
jne dis_cr ; 0D = Carriage return
jmp dis_ff ; 0C = Clear screen
;
; Carriage return
;
dis_cr:
cmp sc_clreol,0
jne dis_vt
discr1:
push dx
cli
mov ax,tsk_regen_o ; current offset
xor dx,dx ; make into doubleword
div sc_cols ; divide by number of columns
sub tsk_regen_o,dx ; subtract remainder
sti
pop dx
jmp disreg_end
;
no_special:
jmp disregen_ok
;
; Backspace
;
dis_bs:
cli
cmp tsk_regen_o,0 ; Handle wraparound
je dis_bs2
sub tsk_regen_o,2
sti
jmp disreg_end
dis_bs2:
mov ax,sc_end ; Wrap to end of screen
sub ax,2
mov tsk_regen_o,ax
sti
jmp disreg_end
;
; Tab
;
dis_tab:
cli
mov ax,tsk_regen_o
add ax,16
and ax,0fff0h ; Tabs every 8 cols
mov tsk_regen_o,ax
sti
jmp disreg_end
;
; Linefeed
;
dis_lf:
cli
mov ax,tsk_regen_o
add ax,sc_cols ; Add one line
mov tsk_regen_o,ax
sti
cmp ax,sc_end ; did we get past the end?
jae dislf_sc
jmp disreg_end
;
dislf_sc:
push es ; then setup regs and go scroll
push di
mov es,tsk_regen_s
mov di,ax
jmp short disreg_scroll
;
; Vertical tab (clear to end of line)
;
dis_vt:
push es
push di
push cx
push ax
les di,tsk_regen
mov cx,sc_cols ; number of columns
mov ax,di ; current offset
xor dx,dx ; make into doubleword
div cx ; divide by number of columns
sub cx,dx ; subtract remainder
shr cx,1 ; number of words
mov ah,tsk_attrib
mov al,' '
rep stosw
pop ax
pop cx
cmp al,0dh
jne disreg_ok
pop di
pop es
jmp discr1
;
; Formfeed (clear to end of screen)
;
dis_ff:
push es
push di
push cx
les di,tsk_regen
mov cx,sc_end ; total number of chars
sub cx,di ; minus current offset
shr cx,1 ; number of words
mov ah,tsk_attrib
mov al,' '
rep stosw
pop cx
jmp short disreg_ok
;
; Normal character output
;
disregen_ok:
push es
push di
cli
les di,tsk_regen ; load current regen buffer addr
mov ah,tsk_attrib
stosw
mov tsk_regen_o,di ; new offset
sti
cmp di,sc_end ; past the end?
jb disreg_ok
;
; Scroll up one line
;
disreg_scroll:
sub di,sc_cols ; one line up
mov tsk_regen_o,di
push cx
push si
push ds
mov si,sc_cols ; second line
mov cx,sc_end
sub cx,si ; screen len minus one line
shr cx,1 ; no. of words
mov di,es
mov ds,di
mov di,0 ; first line
rep movsw
pop ds
;
mov cx,sc_cols ; number of columns
shr cx,1 ; number of words
mov ah,tsk_attrib
mov al,' '
rep stosw
;
pop si
pop cx
;
disreg_ok:
pop di
pop es
;
disreg_end:
call @setcsr
pop ds
ret
;
@disregen endp
;
;
; nodis - local dummy output routine.
; This routine is called if the regen buffer adddress has not
; been set, or if there is no secondary monitor.
;
@nodis proc near
ret
@nodis endp
;
;
; dischar - local screen output routine.
; This routine uses INT 10 TTY output to display the character.
; Entry: AL = char to display
; Uses: AX
;
@dischar proc near
IF IBM
push bx
push bp
mov bl,7
mov ah,14
int 10h
pop bp
pop bx
ELSE
push dx
mov dl,al
mov ah,2
int 21h
pop dx
ENDIF
ret
@dischar endp
;
;
; filechar - local file output routine.
; Write character to file
; Entry: AL = char to display
; Uses: AX
;
@filechar proc near
push bx
push si
mov si,prargdx[bp]
mov bl,ss:[si]
xor bh,bh
inc bx
mov ss:[si+bx],al
cmp bx,FILE_BUFSIZE - 1
jb fcharend
xchg si,dx
inc dx
push ds
push ax
push cx
mov cx,bx
mov bx,prargbx[bp]
mov ax,ss
mov ds,ax
mov ah,40h
int 21h
pop cx
pop ax
pop ds
xchg dx,si
dec si
xor bl,bl
fcharend:
mov ss:[si],bl
pop si
pop bx
ret
@filechar endp
;
;
@poll_com proc near
poll_loop:
add dl,5
in al,dx
sub dl,5
and al,1
jz pollc_end
in al,dx
cmp al,XON
je pollc_xon
cmp al,XOFF
je pollc_xon
push bx
mov bx,tsk_comiptr
mov tsk_combuf[bx],al
cmp tsk_comcnt,16
je pollc_end1
inc bx
and bx,0fh
mov tsk_comiptr,bx
inc tsk_comcnt
pollc_end1:
pop bx
jmp poll_loop
pollc_end:
ret
;
pollc_xon:
mov tsk_comxoff,al
jmp poll_loop
;
@poll_com endp
;
;
; comchar - local comm output routine.
; Write character to comm port
; Entry: AL = char to display
; Uses: AX
;
@comchar proc near
push ds
mov ds,cs:ctdataseg ; allow access to local vars
push dx
mov ah,al
;
mov dx,tsk_comport
or dx,dx
jz cch_end
cch_wxon:
call @poll_com
cmp tsk_comxoff,XOFF
je cch_wxon
add dx,5
cch_wait:
in al,dx
and al,20h ; THRE
jz cch_wait
mov dx,tsk_comport
mov al,ah
out dx,al
;
cch_end:
pop dx
pop ds
ret
@comchar endp
;
;
; stringchar - local string output routine.
; Entry: AL = char to write to string
; prargbx/dx set to point to destination
;
; Uses: AX
;
@stringchar proc near
push di
push es
les di,dword ptr prargbx[bp]
stosb
mov prargbx[bp],di
pop es
pop di
ret
@stringchar endp
;
;
; hexdigbp - put hex digit in AL to SS:DI, increment DI and BL.
;
@hexdigbp proc near
;
push ax
and al,0fh
add al,'0'
cmp al,'9'
jbe hexbp1
add al,prhexch[bp]
hexbp1:
mov byte ptr ss:[di],al
inc di
inc bl
pop ax
ret
;
@hexdigbp endp
;
;
; hexconv - convert hex
; Entry: DX,AX = number
; SS:DI = Buffer pointer
; Exit: BX = converted length
; SS:DI = string start + 1
; Uses: CX
;
@hexconv proc near
xor bl,bl
mov cl,4
mov bh,4
or dx,dx
jnz hchiword
;
hclp1:
call @hexdigbp
shr ax,cl
jz hcend
dec bh
jnz hclp1
;
hcend:
xor bh,bh
ret
;
hchiword:
call @hexdigbp
shr ax,cl
dec bh
jnz hchiword
mov ax,dx
mov bh,4
jmp hclp1
;
@hexconv endp
;
;
; binconv - convert binary
; Entry: DX,AX = number
; SS:DI = Buffer pointer
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -