755 lines
24 KiB
NASM
755 lines
24 KiB
NASM
|
; =====> CPRINT1.ASM
|
|||
|
;***************************************
|
|||
|
;* TIPC Scheme Runtime Support *
|
|||
|
;* S-Expression printing *
|
|||
|
;* *
|
|||
|
;* (C) Copyright 1985 by Texas *
|
|||
|
;* Instruments Incorporated. *
|
|||
|
;* All rights reserved. *
|
|||
|
;* *
|
|||
|
;* Date Written: 24 March 1986 *
|
|||
|
;* Last Modification: 10 Feb 1987 *
|
|||
|
;* *
|
|||
|
;* tc 2/10/87 fixed problem printing *
|
|||
|
;* circular data structs *
|
|||
|
;* rb 1/21/88 binary I/O uses *
|
|||
|
;* line-length = 0; *
|
|||
|
;* set dirty bit on writes *
|
|||
|
;* (commented out) *
|
|||
|
;* *
|
|||
|
;***************************************
|
|||
|
page 60,132
|
|||
|
include scheme.equ
|
|||
|
|
|||
|
P_FLAGS equ 6
|
|||
|
TEST_NUM equ 8
|
|||
|
RETURN equ 0Dh
|
|||
|
SPACE equ 20h
|
|||
|
CUR_COL equ 12
|
|||
|
N_COLS equ 20
|
|||
|
SYM_OVHD equ 7
|
|||
|
HEAPERR equ -3
|
|||
|
|
|||
|
DGROUP group data
|
|||
|
data segment word public 'DATA'
|
|||
|
assume DS:DGROUP
|
|||
|
public display, show, detail, ccount
|
|||
|
extrn port_seg:word
|
|||
|
extrn port_d:word
|
|||
|
extrn port_r:word
|
|||
|
extrn direct:word
|
|||
|
extrn test_ch:word
|
|||
|
extrn t_array:word
|
|||
|
ab_write db "[WARNING: Output aborted by SHIFT-BREAK]",0
|
|||
|
deep_str db "#<DEEP!>",0
|
|||
|
port_str db "#<PORT>",0
|
|||
|
parens db "()",0
|
|||
|
cont_str db "#<CONTINUATION>",0
|
|||
|
ary_str db "#("
|
|||
|
free_str db "#<FREE>",0
|
|||
|
code_str db "#<CODE>",0
|
|||
|
env_str db "#<ENVIRONMENT>",0
|
|||
|
clos_str db "#<PROCEDURE",0
|
|||
|
display dw 1 ; whether to use | and "
|
|||
|
show dw 1 ; whether to send actual char
|
|||
|
detail dw 1 ; whether to show detail
|
|||
|
ccount dw 0 ; character count
|
|||
|
branchtab dw sp_list ; [0] LISTTYPE
|
|||
|
dw sp_fix ; [1] FIXTYPE
|
|||
|
dw sp_flo ; [2] FLOTYPE
|
|||
|
dw sp_big ; [3] BIGTYPE
|
|||
|
dw sp_sym ; [4] SYMTYPE
|
|||
|
dw sp_str ; [5] STRTYPE
|
|||
|
dw sp_ary ; [6] ARYTYPE
|
|||
|
dw sp_cont ; [7] CONTTYPE
|
|||
|
dw sp_clos ; [8] CLOSTYPE
|
|||
|
dw sp_free ; [9] FREETYPE
|
|||
|
dw sp_code ; [10] CODETYPE
|
|||
|
dw sp_ref ; [11] REFTYPE
|
|||
|
dw sp_port ; [12] PORTTYPE
|
|||
|
dw sp_char ; [13] CHARTYPE
|
|||
|
dw sp_env ; [14] ENVTYPE
|
|||
|
data ends
|
|||
|
|
|||
|
PGROUP group prog
|
|||
|
prog segment byte public 'PROG'
|
|||
|
assume CS:PGROUP
|
|||
|
spt_arg struc
|
|||
|
dw ? ; caller's BP
|
|||
|
dw ? ; caller's return address
|
|||
|
pg dw ? ; location of item to be printed
|
|||
|
dis dw ?
|
|||
|
ppg dw ? ; location of output port
|
|||
|
pds dw ?
|
|||
|
spt_arg ends
|
|||
|
extrn setabort:near
|
|||
|
extrn ssetadr:near
|
|||
|
public sprint
|
|||
|
sprint proc near
|
|||
|
push BP
|
|||
|
mov BP,SP
|
|||
|
call setabort ; set address when abort
|
|||
|
xor AX,AX
|
|||
|
mov ccount,AX
|
|||
|
pushm <[BP].pds, [BP].ppg>
|
|||
|
call ssetadr ; set port address
|
|||
|
mov SP,BP
|
|||
|
|
|||
|
;fix for random i/o - note a write has taken place
|
|||
|
lea SI,port_r
|
|||
|
mov BX,[SI].C_page
|
|||
|
LoadPage ES,BX
|
|||
|
mov SI,port_d
|
|||
|
or word ptr ES:[SI+P_FLAGS],DIRTY
|
|||
|
|
|||
|
pushm <[BP].dis, [BP].pg>
|
|||
|
call subsprin ; print it
|
|||
|
mov SP,BP
|
|||
|
mov AX,ccount ; return number of characters
|
|||
|
pop BP
|
|||
|
ret
|
|||
|
sprint endp
|
|||
|
;**************************************************************************
|
|||
|
extrn take_cdr:near
|
|||
|
extrn restart:near
|
|||
|
extrn stkspc:near
|
|||
|
extrn get_sym:near
|
|||
|
extrn givechar:near
|
|||
|
extrn gvchars:near
|
|||
|
extrn copybig:near
|
|||
|
extrn fix2big:near
|
|||
|
extrn big2asc:near
|
|||
|
extrn get_flo:near
|
|||
|
extrn isspace:near
|
|||
|
extrn abort:near
|
|||
|
|
|||
|
subp_arg struc
|
|||
|
tmp_reg1 dw ?
|
|||
|
tmp_reg2 dw ?
|
|||
|
tmp_reg3 dw ?
|
|||
|
tmp_pg dw ?
|
|||
|
tmp_SI dw ?
|
|||
|
ch_buf db 14 dup (0) ; character buffer
|
|||
|
subp_BP dw ? ; caller's BP
|
|||
|
dw ? ; caller's ES
|
|||
|
dw ? ; caller's return address
|
|||
|
spg dw ? ; page number
|
|||
|
sdis dw ? ; displacement
|
|||
|
subp_arg ends
|
|||
|
|
|||
|
subsprin proc near
|
|||
|
push ES
|
|||
|
push BP
|
|||
|
sub SP,offset subp_BP ; allocate local storage
|
|||
|
mov BP,SP
|
|||
|
cmp s_break,0 ; check for SHIFT-BREAK
|
|||
|
je subp_10
|
|||
|
kill_out: mov AX,RETURN ; carriage return
|
|||
|
push AX
|
|||
|
call givechar
|
|||
|
mov SP,BP
|
|||
|
mov AX,41 ; length of message
|
|||
|
lea BX,ab_write
|
|||
|
pushm <AX, BX>
|
|||
|
call printstr ; display message
|
|||
|
mov SP,BP
|
|||
|
cmp show,0
|
|||
|
je kill_01
|
|||
|
xor AX,AX
|
|||
|
jmp kill_02
|
|||
|
kill_01: mov AX,2
|
|||
|
kill_02: push AX ; instruction length
|
|||
|
C_call restart ; link to scheme debugger
|
|||
|
; control does not return to here
|
|||
|
subp_10: call stkspc ; check stack space
|
|||
|
cmp AX,64 ; stack low?
|
|||
|
jge subp_20 ; no, jump
|
|||
|
mov AX,8
|
|||
|
lea BX,deep_str
|
|||
|
pushm <AX, BX>
|
|||
|
call printstr ; print no deeper
|
|||
|
mov SP,BP
|
|||
|
jmp subp_ret
|
|||
|
; act on object type
|
|||
|
subp_20: shl [BP].spg,1 ; adjust page number
|
|||
|
mov BX,[BP].spg
|
|||
|
mov DI,ptype+[BX] ; get port type
|
|||
|
jmp branchtab+[DI]
|
|||
|
|
|||
|
;; the individual type handlers
|
|||
|
|
|||
|
; handle for list
|
|||
|
sp_list: test BX,BX ; null page?
|
|||
|
jnz sp_l01 ; no, jump
|
|||
|
mov AX,2
|
|||
|
lea BX,parens
|
|||
|
pushm <AX, BX>
|
|||
|
call printstr ; print "()"
|
|||
|
mov SP,BP
|
|||
|
jmp subp_ret
|
|||
|
sp_l01: mov DX,28h ; '('
|
|||
|
push DX
|
|||
|
call printcha
|
|||
|
mov SP,BP
|
|||
|
mov BX,[BP].spg ; Get page
|
|||
|
LoadPage ES,BX ; Get paragraph address of page
|
|||
|
mov SI,[BP].sdis ; dispacement
|
|||
|
sp_l02: mov [BP].tmp_pg,BX ; Save page
|
|||
|
mov [BP].tmp_SI,SI ; and displacement
|
|||
|
xor DH,DH
|
|||
|
mov DL,byte ptr ES:[SI] ; Get car's page
|
|||
|
shr DX,1 ; Change to number for subsprin
|
|||
|
mov CX,word ptr ES:[SI+1] ; Get car's displacement
|
|||
|
pushm <CX, DX>
|
|||
|
call subsprin ; Go print it
|
|||
|
mov SP,BP
|
|||
|
mov BX,[BP].tmp_pg ; Restore page
|
|||
|
LoadPage ES,BX ; Its para address
|
|||
|
mov SI,[BP].tmp_SI ; and displacement
|
|||
|
mov BL,byte ptr ES:[SI+3] ; Get cdr's page offset
|
|||
|
mov SI,word ptr ES:[SI+4] ; and displacement
|
|||
|
test BX,BX ; more items in list?
|
|||
|
jz sp_l04 ; no, jump
|
|||
|
mov [BP].tmp_SI,SI ; save registers
|
|||
|
mov [BP].tmp_reg1,BX
|
|||
|
mov DX,SPACE ; print ' '
|
|||
|
push DX
|
|||
|
call printcha
|
|||
|
mov SP,BP
|
|||
|
mov BX,[BP].tmp_reg1 ; restore registers
|
|||
|
mov SI,[BP].tmp_SI
|
|||
|
LoadPage ES,BX ; Get paragraph address of page
|
|||
|
cmp byte ptr ptype+[BX],LISTTYPE*2 ; check port type
|
|||
|
je sp_l02
|
|||
|
; last cdr not nil
|
|||
|
mov [BP].tmp_SI,SI ; save registers
|
|||
|
mov [BP].tmp_reg1,BX
|
|||
|
mov DX,2Eh ; print '.'
|
|||
|
push DX
|
|||
|
call printcha
|
|||
|
mov SP,BP
|
|||
|
mov DX,SPACE ; print ' '
|
|||
|
push DX
|
|||
|
call printcha
|
|||
|
mov SP,BP
|
|||
|
mov BX,[BP].tmp_reg1 ; restore registers
|
|||
|
mov SI,[BP].tmp_SI
|
|||
|
shr BX,1 ; corrected page number
|
|||
|
pushm <SI, BX>
|
|||
|
call subsprin
|
|||
|
mov SP,BP
|
|||
|
sp_l04: mov DX,29h ; print ')'
|
|||
|
push DX
|
|||
|
call printcha
|
|||
|
mov SP,BP
|
|||
|
jmp subp_ret
|
|||
|
; handle for fixnum
|
|||
|
sp_fix: mov AX,5
|
|||
|
mov [BP].tmp_reg2,AX
|
|||
|
push AX
|
|||
|
C_call getmem
|
|||
|
mov SP,BP
|
|||
|
cmp AX,0
|
|||
|
je mem_err
|
|||
|
mov [BP].tmp_reg1,AX ; address of divider
|
|||
|
mov SI,[BP].sdis ; get the value
|
|||
|
shl SI,1
|
|||
|
sar SI,1
|
|||
|
pushm <AX, SI>
|
|||
|
mov AX,DS
|
|||
|
mov ES,AX ; get the right ES segment
|
|||
|
call fix2big ; change to bignum
|
|||
|
mov SP,BP
|
|||
|
jmp printint
|
|||
|
mem_err: mov AX,HEAPERR ; memory not available
|
|||
|
push AX
|
|||
|
call abort
|
|||
|
mov SP,BP
|
|||
|
jmp subp_ret ; return
|
|||
|
; handle for flonum
|
|||
|
sp_flo: mov SI,[BP].sdis ; displacement
|
|||
|
shr BX,1 ; corrected page number
|
|||
|
pushm <SI, BX>
|
|||
|
call get_flo ; get a floating point value
|
|||
|
pushm <AX, BX, CX, DX> ; in AX:BX:CX:DX
|
|||
|
C_call printflo,,Load_ES
|
|||
|
mov SP,BP
|
|||
|
jmp subp_ret
|
|||
|
; handle for array
|
|||
|
sp_ary: mov AX,2
|
|||
|
LoadPage ES,BX ; page segment
|
|||
|
lea BX,ary_str ; print "#("
|
|||
|
pushm <AX, BX>
|
|||
|
call printstr
|
|||
|
mov SP,BP
|
|||
|
|
|||
|
LoadPage ES,[BP].spg ; Get page address of array
|
|||
|
;;; mov ES,word ptr pagetabl+[BX]
|
|||
|
mov SI,[BP].sdis ; and segment
|
|||
|
mov CX,word ptr ES:[SI+1]
|
|||
|
sub CX,BLK_OVHD ; length of array
|
|||
|
mov BX,BLK_OVHD
|
|||
|
mov [BP].tmp_reg1,CX
|
|||
|
sp_a01:
|
|||
|
cmp BX,[BP].tmp_reg1
|
|||
|
jle sp_a04
|
|||
|
jmp sp_l04
|
|||
|
sp_a04: mov AL,byte ptr ES:[SI+BX] ; AX <= page of array element
|
|||
|
mov DX,word ptr ES:[SI+BX+1] ; DX <= disp. of array element
|
|||
|
xor AH,AH
|
|||
|
shr AX,1 ; Page number for subsprin
|
|||
|
mov [BP].tmp_reg2,BX ; Save registers
|
|||
|
mov [BP].tmp_SI,SI
|
|||
|
pushm <DX, AX>
|
|||
|
call subsprin ; print element
|
|||
|
mov SP,BP
|
|||
|
mov BX,[BP].tmp_reg2 ; restore BX
|
|||
|
cmp BX,[BP].tmp_reg1 ; last element?
|
|||
|
jge sp_a02
|
|||
|
mov DX,SPACE ; print ' '
|
|||
|
push DX
|
|||
|
call printcha
|
|||
|
mov SP,BP
|
|||
|
mov BX,[BP].tmp_reg2 ; restore registers
|
|||
|
sp_a02: mov SI,[BP].tmp_SI
|
|||
|
add BX,PTRSIZE
|
|||
|
LoadPage ES,[BP].spg ; Reload page address of array
|
|||
|
jmp sp_a01
|
|||
|
; handle for continuation
|
|||
|
sp_cont: mov AX,15
|
|||
|
lea BX,cont_str
|
|||
|
pushm <AX, BX>
|
|||
|
call printstr
|
|||
|
mov SP,BP
|
|||
|
jmp subp_ret
|
|||
|
; handle for closure
|
|||
|
sp_clos: mov AX,11
|
|||
|
lea BX,clos_str
|
|||
|
pushm <AX, BX>
|
|||
|
call printstr ; print "#<PROCEDURE"
|
|||
|
; fetch information operand from closure object
|
|||
|
LoadPage ES,[BP].spg ; Get address of page
|
|||
|
mov SI,[BP].sdis
|
|||
|
lea BX,[BP].tmp_reg1
|
|||
|
xor AH,AH
|
|||
|
mov AL,byte ptr ES:[SI+3] ; Page # of information op
|
|||
|
mov [BX].C_page,AX
|
|||
|
mov AX,word ptr ES:[SI+4] ; Disp of information op
|
|||
|
mov [BX].C_disp,AX
|
|||
|
; follow information operand list to cdr of last list cell
|
|||
|
sp_c001: mov DI,[BX].C_page
|
|||
|
cmp DI,0
|
|||
|
je sp_c01
|
|||
|
cmp byte ptr ptype+[DI],LISTTYPE*2
|
|||
|
jne sp_c01
|
|||
|
push BX
|
|||
|
call take_cdr
|
|||
|
lea BX,[BP].tmp_reg1
|
|||
|
jmp sp_c001
|
|||
|
; If final operand is a symbol, print it
|
|||
|
sp_c01: cmp byte ptr ptype+[DI],SYMTYPE*2
|
|||
|
jne sp_c04
|
|||
|
LoadPage ES,DI
|
|||
|
mov SI,[BX].C_disp
|
|||
|
mov BX,word ptr ES:[SI+1] ; get the object size
|
|||
|
sub BX,BLK_OVHD+PTRSIZE
|
|||
|
push DI ; temp-save DI
|
|||
|
push BX
|
|||
|
dec BX
|
|||
|
mov [BP].tmp_reg3,BX ; BX = symbol length
|
|||
|
C_call getmem
|
|||
|
pop DI ; (get getmem arg off stack)
|
|||
|
pop DI ; temp-restore DI
|
|||
|
mov SP,BP
|
|||
|
cmp AX,0 ; memory available?
|
|||
|
jne sp_c02
|
|||
|
jmp mem_err ; no, jump
|
|||
|
sp_c02: mov [BP].tmp_reg2,AX
|
|||
|
sar DI,1
|
|||
|
mov CX,DS ; ES points to DS segment
|
|||
|
mov ES,CX
|
|||
|
pushm <[BP].tmp_reg1, DI, AX> ; [tmp_reg1] = disp
|
|||
|
call get_sym ; get the symbol name
|
|||
|
mov SP,BP
|
|||
|
mov DX,SPACE
|
|||
|
push DX
|
|||
|
call printcha ; print ' '
|
|||
|
mov SP,BP
|
|||
|
pushm <[BP].tmp_reg3, [BP].tmp_reg2>
|
|||
|
call printstr ; print the symbol name
|
|||
|
mov SP,BP
|
|||
|
mov BX,[BP].tmp_reg3
|
|||
|
inc BX
|
|||
|
pushm <BX, [BP].tmp_reg2>
|
|||
|
C_call rlsmem
|
|||
|
mov SP,BP
|
|||
|
sp_c04: mov DX,3Eh
|
|||
|
push DX
|
|||
|
call printcha ; print '>'
|
|||
|
mov SP,BP
|
|||
|
jmp subp_ret
|
|||
|
; handle for free
|
|||
|
sp_free: mov AX,7
|
|||
|
lea BX,free_str
|
|||
|
pushm <AX, BX>
|
|||
|
call printstr ; print #<FREE>
|
|||
|
mov SP,BP
|
|||
|
jmp subp_ret
|
|||
|
; handle for code block
|
|||
|
sp_code: mov AX,7
|
|||
|
lea BX,code_str
|
|||
|
pushm <AX, BX>
|
|||
|
call printstr ; print #<CODE>
|
|||
|
mov SP,BP
|
|||
|
jmp subp_ret
|
|||
|
; handle for environment
|
|||
|
sp_env: mov AX,14
|
|||
|
lea BX,env_str
|
|||
|
pushm <AX, BX>
|
|||
|
call printstr ; print #<ENVIRONMENT>
|
|||
|
mov SP,BP
|
|||
|
jmp subp_ret
|
|||
|
; handle for symbol
|
|||
|
sp_sym: mov AX,7Ch
|
|||
|
mov CX,SYM_OVHD
|
|||
|
mov SI,[BP].sdis
|
|||
|
shr BX,1 ; corrected page number
|
|||
|
pushm <AX, CX, SI, BX>
|
|||
|
C_call printatm,,Load_ES ; print the symbol
|
|||
|
mov SP,BP
|
|||
|
jmp subp_ret
|
|||
|
; handle for string
|
|||
|
sp_str: LoadPage ES,BX ; Get address of page
|
|||
|
mov SI,[BP].sdis ; and displacement
|
|||
|
mov CX,word ptr ES:[SI+1]
|
|||
|
cmp CX,0 ; check for small string
|
|||
|
jge sp_s01
|
|||
|
add CX,BLK_OVHD+PTRSIZE
|
|||
|
sp_s01: sub CX,BLK_OVHD ; get the string length
|
|||
|
mov [BP].tmp_reg1,CX ; save the string length
|
|||
|
mov DX,ccount
|
|||
|
add DX,CX
|
|||
|
mov ccount,DX
|
|||
|
cmp show,0
|
|||
|
jne sp_s02
|
|||
|
jmp subp_ret
|
|||
|
sp_s02: add SI,BLK_OVHD ; advance pointer to string
|
|||
|
mov [BP].tmp_SI,SI
|
|||
|
cmp display,0
|
|||
|
jne sp_s02a
|
|||
|
jmp sp_sdis
|
|||
|
; write, need to print double quotes, escape characters
|
|||
|
sp_s02a: xor BX,BX
|
|||
|
mov DX,2 ; strange = 2
|
|||
|
sp_s001: cmp BX,CX
|
|||
|
jge sp_s05
|
|||
|
mov AL,byte ptr ES:[SI+BX]
|
|||
|
cmp AL,5Ch ; check for \
|
|||
|
je sp_s03
|
|||
|
cmp AL,22h ; check for "
|
|||
|
jne sp_s04
|
|||
|
sp_s03: inc DX
|
|||
|
sp_s04: inc BX
|
|||
|
jmp sp_s001
|
|||
|
sp_s05: add DX,CX ; strange + len
|
|||
|
push DX
|
|||
|
call wrap
|
|||
|
mov AX,22h
|
|||
|
push AX
|
|||
|
call givechar ; print " for string
|
|||
|
mov SP,BP
|
|||
|
xor BX,BX
|
|||
|
mov SI,[BP].tmp_SI
|
|||
|
sp_s06: cmp BX,[BP].tmp_reg1 ; finish the string?
|
|||
|
jge sp_s10
|
|||
|
cmp s_break,0 ; check for SHIFT-BREAK
|
|||
|
je sp_s07
|
|||
|
jmp kill_out ; yes, jump
|
|||
|
sp_s07:
|
|||
|
LoadPage ES,[BP].spg ; Ensure string page loaded
|
|||
|
mov DL,byte ptr ES:[SI+BX] ; Get one character
|
|||
|
xor DH,DH
|
|||
|
mov [BP].tmp_reg2,BX ; save registers
|
|||
|
cmp DL,5Ch ; \?
|
|||
|
je sp_s08
|
|||
|
cmp DL,22h ; "?
|
|||
|
jne sp_s09
|
|||
|
sp_s08: mov AX,5Ch
|
|||
|
mov [BP].tmp_reg3,DX ; save the character
|
|||
|
push AX
|
|||
|
call givechar ; print the \ for special
|
|||
|
mov SP,BP
|
|||
|
mov DX,[BP].tmp_reg3
|
|||
|
sp_s09: push DX
|
|||
|
call givechar ; print the character
|
|||
|
mov SP,BP
|
|||
|
mov SI,[BP].tmp_SI ; restore registers
|
|||
|
mov BX,[BP].tmp_reg2
|
|||
|
inc BX
|
|||
|
jmp sp_s06
|
|||
|
sp_s10: mov AX,22h
|
|||
|
push AX
|
|||
|
call givechar ; print "
|
|||
|
mov SP,BP
|
|||
|
jmp subp_ret
|
|||
|
; display, just print the string
|
|||
|
sp_sdis: push CX
|
|||
|
call wrap
|
|||
|
xor BX,BX
|
|||
|
mov SI,[BP].tmp_SI
|
|||
|
sp_s11: cmp BX,[BP].tmp_reg1 ; finish the string?
|
|||
|
jl sp_s12
|
|||
|
jmp subp_ret ; yes, return
|
|||
|
sp_s12: cmp s_break,0 ; check for SHIFT-BREAK
|
|||
|
je sp_s13
|
|||
|
jmp kill_out ; yes, jump
|
|||
|
sp_s13: xor AH,AH
|
|||
|
LoadPage ES,[BP].spg ; Ensure string page loaded
|
|||
|
mov AL,byte ptr ES:[SI+BX] ; get the character
|
|||
|
push AX
|
|||
|
mov [BP].tmp_reg2,BX ; save registers
|
|||
|
call givechar ; print the character
|
|||
|
mov SP,BP
|
|||
|
mov BX,[BP].tmp_reg2 ; restore registers
|
|||
|
mov SI,[BP].tmp_SI
|
|||
|
inc BX ; increment the index
|
|||
|
jmp sp_s11
|
|||
|
; handle for character
|
|||
|
sp_char: mov SI,[BP].sdis
|
|||
|
and SI,00FFh ; get the low byte for character
|
|||
|
cmp display,0
|
|||
|
je sp_c10
|
|||
|
mov AX,SI ; AL = character
|
|||
|
lea SI,[BP].ch_buf
|
|||
|
mov byte ptr [SI],23h ; #
|
|||
|
mov byte ptr [SI+1],5Ch ; \
|
|||
|
mov byte ptr [SI+2],AL ; character
|
|||
|
mov byte ptr [SI+3],0 ; end of string
|
|||
|
; check for a special multi-character character constant
|
|||
|
xor BX,BX
|
|||
|
lea DI,test_ch
|
|||
|
sp_ch01: cmp BX,TEST_NUM ; end of comparison?
|
|||
|
jl sp_ch02
|
|||
|
mov BX,3 ; yes
|
|||
|
jmp sp_ch12
|
|||
|
sp_ch02: cmp AL,byte ptr [DI+BX] ; compare with special char
|
|||
|
je sp_ch05
|
|||
|
inc BX
|
|||
|
jmp sp_ch01
|
|||
|
sp_ch05: lea DI,t_array
|
|||
|
shl BX,1 ; get the word offset
|
|||
|
mov DI,word ptr [DI+BX] ; pointer to special char string
|
|||
|
mov BX,2
|
|||
|
sp_ch03: cmp byte ptr [DI],0 ; end of string?
|
|||
|
je sp_ch04 ; yes, jump
|
|||
|
mov AL,byte ptr [DI]
|
|||
|
mov byte ptr [SI+BX],AL ; move character by character
|
|||
|
inc BX
|
|||
|
inc DI
|
|||
|
jmp sp_ch03
|
|||
|
sp_ch04: mov byte ptr [SI+BX],0 ; end of string
|
|||
|
sp_ch12: pushm <BX, SI> ; BX = length of buffer
|
|||
|
call printstr
|
|||
|
mov SP,BP
|
|||
|
jmp subp_ret
|
|||
|
; print character without escapes
|
|||
|
sp_c10: push SI
|
|||
|
call printcha
|
|||
|
mov SP,BP
|
|||
|
jmp subp_ret
|
|||
|
; handle for bignum
|
|||
|
sp_big: LoadPage ES,BX
|
|||
|
mov SI,[BP].sdis
|
|||
|
mov AX,word ptr ES:[SI+1] ; get object size
|
|||
|
dec AX
|
|||
|
mov [BP].tmp_reg2,AX
|
|||
|
push AX
|
|||
|
C_call getmem ; allocate memory for divider
|
|||
|
mov SP,BP
|
|||
|
cmp AX,0 ; memory available?
|
|||
|
jne sp_big1
|
|||
|
jmp mem_err ; no, error
|
|||
|
sp_big1: mov [BP].tmp_reg1,AX ; address of divider
|
|||
|
mov BX,[BP].spg
|
|||
|
shr BX,1
|
|||
|
pushm <AX, [BP].sdis, BX>
|
|||
|
mov AX,DS
|
|||
|
mov ES,AX ; get the right ES segment
|
|||
|
call copybig ; copy bignum to buffer
|
|||
|
printint:
|
|||
|
mov AX,[BP].tmp_reg2
|
|||
|
mov BX,3
|
|||
|
mul BX
|
|||
|
sub AX,5
|
|||
|
mov [BP].tmp_SI,AX
|
|||
|
push AX
|
|||
|
C_call getmem ; allocate memory for char buffer
|
|||
|
mov SP,BP
|
|||
|
cmp AX,0 ; memory available?
|
|||
|
jne sp_big2
|
|||
|
jmp mem_err ; no, error
|
|||
|
sp_big2: mov [BP].tmp_reg3,AX ; address of bigchars
|
|||
|
pushm <AX,[BP].tmp_reg1>
|
|||
|
call big2asc ; convert bignum to char string
|
|||
|
mov SP,BP ; AX = characters count
|
|||
|
pushm <AX, [BP].tmp_reg3>
|
|||
|
call printstr ; print the bignum
|
|||
|
mov SP,BP
|
|||
|
pushm <[BP].tmp_reg2, [BP].tmp_reg1>
|
|||
|
C_call rlsmem
|
|||
|
pushm <[BP].tmp_SI, [BP].tmp_reg3>
|
|||
|
C_call rlsmem
|
|||
|
mov SP,BP
|
|||
|
jmp subp_ret
|
|||
|
; handle for port
|
|||
|
sp_port: mov AX,7
|
|||
|
lea BX,port_str
|
|||
|
pushm <AX, BX>
|
|||
|
call printstr ; print #<PORT>
|
|||
|
mov SP,BP
|
|||
|
sp_ref:
|
|||
|
subp_ret: add SP,offset subp_BP ; release local storage
|
|||
|
pop BP
|
|||
|
pop ES
|
|||
|
ret
|
|||
|
subsprin endp
|
|||
|
;******************************************************************************
|
|||
|
; Print a single character to the file, and send a newline
|
|||
|
; if necessary.
|
|||
|
;******************************************************************************
|
|||
|
pch_arg struc
|
|||
|
dw ? ; caller's BP
|
|||
|
dw ? ; caller's return address
|
|||
|
cha dw ? ; character
|
|||
|
pch_arg ends
|
|||
|
|
|||
|
printcha proc near
|
|||
|
push BP
|
|||
|
mov BP,SP
|
|||
|
inc ccount ; ccount++
|
|||
|
cmp show,0 ; show?
|
|||
|
je prch_ret ; no, return
|
|||
|
call currspc ; check spaces remaining
|
|||
|
cmp AX,0
|
|||
|
jle prch_01
|
|||
|
prch_001: push [BP].cha
|
|||
|
call givechar
|
|||
|
mov SP,BP
|
|||
|
jmp prch_ret ; return to caller
|
|||
|
prch_01: test direct,BINARY
|
|||
|
jnz prch_001
|
|||
|
mov AX,RETURN
|
|||
|
push AX
|
|||
|
call givechar ; newline
|
|||
|
mov SP,BP
|
|||
|
push [BP].cha
|
|||
|
call isspace ; after newline, print nonspaces
|
|||
|
test AX,AX
|
|||
|
jnz prch_ret ; space, return
|
|||
|
jmp prch_001
|
|||
|
prch_ret: pop BP
|
|||
|
ret ; return to caller
|
|||
|
printcha endp
|
|||
|
;******************************************************************************
|
|||
|
; Print the string with length LEN, first sending a newline
|
|||
|
; if necessary.
|
|||
|
;******************************************************************************
|
|||
|
str_arg struc
|
|||
|
dw ? ; caller's BP
|
|||
|
dw ? ; caller's return address
|
|||
|
str dw ? ; string pointer
|
|||
|
len dw ? ; string length
|
|||
|
str_arg ends
|
|||
|
public printstr
|
|||
|
printstr proc near
|
|||
|
push BP
|
|||
|
mov BP,SP
|
|||
|
push [BP].len
|
|||
|
call wrap ; check available spaces
|
|||
|
mov AX,ccount
|
|||
|
add AX,[BP].len ; ccount += len
|
|||
|
mov ccount,AX
|
|||
|
cmp show,0 ; show?
|
|||
|
je pstr_ret ; no, return
|
|||
|
pushm <[BP].len, [BP].str>
|
|||
|
call gvchars ; display all characters
|
|||
|
pstr_ret: pop BP
|
|||
|
ret
|
|||
|
printstr endp
|
|||
|
;******************************************************************************
|
|||
|
; Return number of spaces remaining on current line
|
|||
|
;******************************************************************************
|
|||
|
currspc proc near
|
|||
|
pop DI ; get the return address
|
|||
|
push ES
|
|||
|
push SI
|
|||
|
lea SI,port_r
|
|||
|
mov SI,[SI].C_page
|
|||
|
LoadPage ES,SI
|
|||
|
;;; LoadPage ES,port_seg ; Get port para address
|
|||
|
mov SI,port_d
|
|||
|
mov AX,word ptr ES:[SI+N_COLS] ; line length
|
|||
|
test AX,AX ; line length defined?
|
|||
|
jnz curr_01
|
|||
|
mov AX,-1 ; no, return negative value
|
|||
|
jmp curr_02
|
|||
|
curr_01: sub AX,word ptr ES:[SI+CUR_COL]
|
|||
|
curr_02: pop SI
|
|||
|
pop ES
|
|||
|
jmp DI ; return to caller
|
|||
|
currspc endp
|
|||
|
;******************************************************************************
|
|||
|
; Return current column
|
|||
|
;******************************************************************************
|
|||
|
curr_col proc near
|
|||
|
pop DI ; get the return address
|
|||
|
push ES
|
|||
|
push SI
|
|||
|
lea SI,port_r
|
|||
|
mov SI,[SI].C_page
|
|||
|
LoadPage ES,SI
|
|||
|
;;; LoadPage ES,port_seg ; Get port para address
|
|||
|
mov SI,port_d
|
|||
|
mov AX,word ptr ES:[SI+N_COLS] ; Get Number of columns
|
|||
|
or AX,AX ; Maintaining column?
|
|||
|
jz ccol_ret ; No, just return 0
|
|||
|
mov AX,word ptr ES:[SI+CUR_COL] ; Yes, get column and return
|
|||
|
ccol_ret: pop SI
|
|||
|
pop ES
|
|||
|
jmp DI ; return to caller
|
|||
|
curr_col endp
|
|||
|
;******************************************************************************
|
|||
|
; Wrap issues a newline if there are less than LEN spaces
|
|||
|
; left on the current output line.
|
|||
|
; Note: DX = LEN
|
|||
|
;******************************************************************************
|
|||
|
public wrap
|
|||
|
wrap proc near
|
|||
|
pop DI ; get the return address
|
|||
|
pop DX ; get the length
|
|||
|
cmp show,0
|
|||
|
jz wrap_ret
|
|||
|
push DI ; save return address
|
|||
|
call curr_col ; get the current column number
|
|||
|
pop DI ; restore return address
|
|||
|
cmp AX,1
|
|||
|
jle wrap_ret
|
|||
|
push DI ; save return address
|
|||
|
call currspc ; get the available spaces
|
|||
|
pop DI ; restore return address
|
|||
|
cmp AX,DX
|
|||
|
jge wrap_ret
|
|||
|
mov AX,RETURN ; issue a newline
|
|||
|
push AX
|
|||
|
call givechar
|
|||
|
mov SP,BP
|
|||
|
wrap_ret: jmp DI ; return to caller
|
|||
|
wrap endp
|
|||
|
|
|||
|
prog ends
|
|||
|
end
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|