;-------------------------------------
; Version 1.1
; iuput: DS:SI text string (end with 0) followed with parameters
; control char: use '%' first
; %[-][,][nn][l|s]<b|o|d|h>
; - ==> print neg number with use dec
; , ==> use , spar per 3 numbers
; nn ==> print width,bland left fill
; if 0nn, 0 left fill
; l/s ==> data as Dword/byte,ignore=word
; b/o/d/h ==> format in bin/oct/dec/hex
; %c ==> data as String(end with 0)
; %[nn]C ==> data as string(end with 0)
; nn ==> print nn bytes, fill right with blank
; %<nn>r<Char> ==> fill nn numbers of Char
; %<nn>t ==> fill space to nn
STD_OUT DW PRT_TO_SCR ;output Proc address
TABLE_COUNT DW ?
VAR_PTR DW ? ;start point of parameter
FILL_CHAR DB ' ' ;fill char in %xx format
SPAR_NUM DB 0 ;how many char/spar
PRT_FLAG DB ?
; bit0 ------ use spar
; bit1 ------ signal
; bit2 ------ quiet mode
HEX_TABLE DB '0123456789ABCDEF'
PRINTF PROC
pusha
push var_ptr
push word ptr prt_flag
cld
mov di,si
xor al,al
mov cx,-1
repnz scasb
mov var_ptr,di
and prt_flag,11111100b ;clear spar and neg flag
prt_lop:
lodsb
or al,al
jnz print_it
pop word ptr prt_flag
pop var_ptr
popa
ret
print_it:
cmp al,'%' ;is control char
jz prt_ctrl ;jump to prt_ctrl
prt_1:
call std_out
jmp short prt_lop
prt_ctrl:
and prt_flag,11111101b ;clear spar and neg flag
prt_ctrl1:
cmp byte ptr [si],'-' ;if neg
jz ctrl_sub
cmp byte ptr [si],',' ;if spar
jnz signal
or prt_flag,00000001b
inc si
jmp short prt_lop
ctrl_sub:
or prt_flag,00000010b
inc si
jmp short prt_ctrl1
signal:
call get_num_len ;get format length in BP
lodsb
cmp al,'%' ;print '%'
jz prt_1
cmp al,'c' ;print string
jz prt_string
cmp al,'C'
jz prt_string1
cmp al,'r' ;fill char
jz prt_repc
cmp al,'t'
jz prt_table
dec si ;other return the char
call get_num ;get parameter
call prt_space ;format width
call prt_num ;print out parameter
jmp short prt_lop
prt_repc:
lodsb ;get fill char
mov cx,bp
or cx,cx
jz prt_lop
prt_repc_lop:
push ax
call std_out
pop ax
loop prt_repc_lop
_prt_lop:
jmp short prt_lop
prt_string1:
push si
mov si,var_ptr
add var_ptr,2
mov si,[si]
or bp,bp
jz prtstr_ret
mov cx,bp
prtstr_lop:
lodsb
or al,al
jz prtstr_lop1
call std_out
loop prtstr_lop
jmp short prtstr_ret
prtstr_lop1:
mov al,20h
call std_out
loop prtstr_lop1
prtstr_ret:
pop si
jmp short _prt_lop
prt_string:
push si ;print string
mov si,var_ptr
add var_ptr,2
mov si,[si]
call printf
pop si
jmp short _prt_lop
prt_table:
cmp bp,table_count
jbe _prt_lop
mov al,20h
call std_out
jmp short prt_table
;-------------------------------
; get data format length
; return BP = format length
GET_NUM_LEN PROC
lodsb
mov cx,0a00h
mov fill_char,' ' ;nn format ' ' left fill
cmp al,'0'
jnz gnl_lop
mov fill_char,'0' ;0nn format then '0' left fill
gnl_lop:
cmp al,'0' ;not 0 to 9 end
jb gnl_ret
cmp al,'9'
ja gnl_ret
sub al,'0'
push ax
mov al,cl ;final result may in CL
mul ch
mov cl,al
pop ax
add cl,al
lodsb
jmp short gnl_lop
gnl_ret:
dec si ;not 0 to 9 return this char
xor ch,ch
mov bp,cx ;store result in BP
ret
GET_NUM_LEN ENDP
;--------------------------------
; get data in DX:AX
GET_NUM PROC
lodsb
mov cl,al
cmp al,'l' ;long
jz gn_ls
cmp al,'s' ;short
jnz gn_1
gn_ls:
lodsb ;if is 'l' or 's' get following char
gn_1:
cmp al,'b' ;bin
jz gn_bin
cmp al,'o' ;oct
jz gn_oct
cmp al,'d' ;dec
jz gn_dec
cmp al,'h' ;hex
jnz gn_dec
mov di,16
mov al,4
jmp short gn_2
gn_bin:
mov di,2
mov al,8
jmp short gn_2
gn_oct:
mov di,8
mov al,4
jmp short gn_2
gn_dec:
mov di,10
mov al,3
gn_2:
mov spar_num,al
mov bx,var_ptr
add var_ptr,2
mov bx,[bx] ;bx = parameter address
xor dx,dx
mov ax,[bx] ;get parameter
cmp cl,'s'
jz gn_short
cmp cl,'l'
jz gn_long
mov ax,[bx]
test prt_flag,00000010b
jz gn_ret
cwd
ret
gn_long:
mov dx,[bx+2]
ret
gn_short:
xor ah,ah
test prt_flag,00000010b
jz gn_ret
cbw
cwd
gn_ret:
ret
GET_NUM ENDP
;-------------------------------------
; calculate and print in DI base
; input: DX:AX = data
; DI = number base
PRT_NUM PROC
xor bp,bp ;spar use
cmp di,10 ;base 10 check +/- flag
jnz prt_num1
test prt_flag,00000010b ; +/-
jz prt_num1
test dx,8000h ;is -
jz prt_num1
not dx
not ax
add ax,1
adc dx,0
push ax
mov al,'-'
call std_out
pop ax
prt_num1:
inc bp ;BP = data width
push ax
mov ax,dx
xor dx,dx
div di
mov bx,ax
pop ax
div di
xchg bx,dx
push ax
or ax,dx
pop ax
jz prt_inc_1
push bx
call prt_num1
pop bx
prt_inc_1:
mov al,hex_table [bx]
call std_out
test prt_flag,00000001b ;use ,
jz prt_inc_2
dec bp
mov ax,bp
div spar_num
or al,al
jz prt_inc_2
or ah,ah
jnz prt_inc_2
mov al,','
call std_out
prt_inc_2:
ret
PRT_NUM ENDP
;---------------------------------------
; input: BP = data format length
; DX:AX = data
PRT_SPACE PROC
pusha
push std_out
mov std_out,offset prt_count
xor cx,cx
push bp
call prt_num ;count has how many chars
pop bp ;return CX = chars
pop std_out
push bp
xchg cx,bp
sub cx,bp
pop bp
cmp cx,0
jle prt_space1
prt_space_lop:
mov ax,bp
mov bl,spar_num
inc bl
dec bp
div bl
mov al,fill_char
test prt_flag,00000001b
jz ps_prt
or ah,ah
jnz ps_prt
cmp al,' '
jz ps_prt
mov al,','
ps_prt:
call std_out
loop prt_space_lop
prt_space1:
popa
ret
PRT_SPACE ENDP
;--------------------------------
; count for %xx format
PRT_COUNT PROC
inc cx
ret
PRT_COUNT ENDP
;-------------------------------------
; print to screen proc
; don't change resigter except AX
PRT_TO_SCR PROC
cmp al,0dh
jnz pts_1
mov table_count,0
jmp short pts_3
pts_1:
cmp al,08h
jnz pts_2
dec table_count
jmp short pts_3
pts_2:
inc table_count
pts_3:
test prt_flag,00000100b
jnz pts_ret
mov ah,0eh
mov bl,7
int 10h
pts_ret:
ret
PRT_TO_SCR ENDP
PRINTF ENDP