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

📄 tskprf.asm

📁 一个多任务操作系统CTask的源代码 用C语言编写
💻 ASM
📖 第 1 页 / 共 3 页
字号:
;
;	--- 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 + -