⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 tskprf.asm

📁 用TC2实现的DOS多任务功能
💻 ASM
📖 第 1 页 / 共 2 页
字号:
;
;	--- Version 2.2 90-10-12 10:38 ---
;
;	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
;
;	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
;
	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
;
	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
;
	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
;
;
; 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	11 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
;
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
;
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
;
;
; 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
	jmp	hclp1
;
@hexconv	endp
;
;
;	decconv - convert decimal
;
;	Entry:	DX,AX = number
;		SS:DI = Buffer top pointer
;	Exit:	BX    = converted length
;		SS:DI = string start + 1
;	Uses:	CX
;
@decconv	proc	near
	xor	bx,bx
	mov	cx,10
	or	dx,dx
	jnz	dchiword
;
dclp1:
	xor	dx,dx
	div	cx
	add	dl,'0'
	mov	byte ptr ss:[di],dl
	inc	di
	inc	bx
	or	ax,ax
	jnz	dclp1
	ret
;
dchiword:
	push	si
	mov	si,dx
;
dchilp:
	xchg	ax,si
	xor	dx,dx
	div	cx
	xchg	ax,si
	div	cx
	add	dl,'0'
	mov	byte ptr ss:[di],dl
	inc	di
	inc	bx
	or	si,si
	jnz	dchilp
;
	pop	si
	jmp	dclp1
;
@decconv	endp
;
;
; getint - read integer at DS:SI
;	Entry: AL = first char
;	Exit:  AX = integer
;	Uses:  BX,DX
;
@getint	proc	near
;
	and	ax,0fh
	mov	bl,10
getintlp:
	xchg	ax,dx
	lodsb
	cmp	al,'0'
	jb	getint_end
	cmp	al,'9'
	ja	getint_end
	and	ax,0fh
	xchg	ax,dx
	mul	bl
	add	ax,dx
	jmp	getintlp
;
getint_end:
	dec	si
	mov	ax,dx
	ret
;
@getint	endp
;
;
;	padleft - local routine to pad output on the left side.
;
@padleft	proc	near
;
	push	cx
	push	dx
	xor	dx,dx
	test	prflags[bp],F_PREC
	jz	padleft_noprec
	cmp	bx,prec[bp]
	jae	padleft_noprec
;
	mov	dx,prec[bp]
	sub	dx,bx
	test	prflags[bp],F_WIDTH
	jz	padleft_noprec
	sub	prwidth[bp],dx
	jnc	padleft_noprec
	and	prflags[bp],NOT F_WIDTH
;
padleft_noprec:
	test	prflags[bp],F_LEFTADJ
	jnz	padleft_end
	test	prflags[bp],F_WIDTH
	jz	padleft_end
	cmp	bx,prwidth[bp]
	jae	padleft_end
;
	mov	cx,prwidth[bp]
	sub	cx,bx
	add	procnt[bp],cx
	mov	al,' '
	test	prflags[bp],F_PADZERO
	jz	padleftlp
	mov	al,'0'
;
padleftlp:
	push	ax
	call	prproc[bp]
	pop	ax
	loop	padleftlp
;
padleft_end:
	mov	cx,dx
	jcxz	padleft_exit
	add	procnt[bp],cx
;
padleftprec:
	mov	al,'0'
	call	prproc[bp]
	loop	padleftprec
;
padleft_exit:
	pop	dx
	pop	cx
	ret
;
@padleft	endp
;
;	padright - local routine to pad output on the right side
;
@padright	proc	near
;
	test	prflags[bp],F_LEFTADJ
	jz	padright_end
	test	prflags[bp],F_WIDTH
	jz	padright_end
	cmp	bx,prwidth[bp]
	jae	padright_end
;
	push	cx
	mov	cx,prwidth[bp]
	sub	cx,bx
	add	procnt[bp],cx
;
padrightlp:
	mov	al,' '
	call	prproc[bp]
	loop	padrightlp
	pop	cx
;
padright_end:
	ret
;
@padright	endp
;
;
; disprintf: display formatted string.
;
; 	Entry:	DS:SI = format string
; 		ES:DI = parameter pointer
;		CX    = output routine address
;		BX,DX = output routine parameter
;
;	Uses:	AX,BX,DX
;
;	Usually, the parameter pointer will point to the first
;	parameter on the stack. For added flexibility, ES:DI is
;	used here, so that the parameter list may be anywhere in
;	memory. This allows vprintf-style parameters.
;
;
@disprintf	proc	near
	push	bp
	sub	sp,TYPE dislocrec
	mov	bp,sp
	mov	prproc[bp],cx
	mov	prargbx[bp],bx
	mov	prargdx[bp],dx
	mov	procnt[bp],0
;
disploop:
	lodsb
	or	al,al
	jz	dispend			; end of string
	cmp	al,'%'
	je	dispformat		; jump if format character
	cmp	al,0ah
	jne	dispchar
	mov	al,0dh
	call	prproc[bp]		; translate LF into CR+LF
	inc	procnt[bp]
	mov	al,0ah
;
dispchar:
	call	prproc[bp]
	inc	procnt[bp]
	jmp	disploop
;
dispend:
	mov	bx,prargbx[bp]
	add	sp,TYPE dislocrec
	pop	bp
	ret
;
disploop1:
	pop	di
	pop	es
	add	di,arglen[bp]
	jmp	disploop
;
;	Format character found, process conversion
;
dispformat:
	lodsb
	cmp	al,'%'		; %% means print single %
	je	dispchar
;
	push	es
	push	di		; save parameter pointer
	mov	prflags[bp],0
	mov	arglen[bp],2
;
	cmp	al,'-'
	jne	no_flags
	or	prflags[bp],F_LEFTADJ
	lodsb
;
no_flags:
	cmp	al,'0'
	jne	no_zero
	or	prflags[bp],F_PADZERO
	lodsb
;
no_zero:
	cmp	al,'*'
	je	loadwidth
	cmp	al,'9'
	ja	no_width
	cmp	al,'0'
	jb	no_width
	call	@getint
	jmp	short haswidth

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -