pcs/sio.asm

292 lines
12 KiB
NASM
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

; =====> SIO.ASM
;***************************************
;* TIPC Scheme '84 Runtime Support *
;* I/O Utilities *
;* *
;* (C) Copyright 1984,1985 by Texas *
;* Instruments Incorporated. *
;* All rights reserved. *
;* *
;* Date Written: June 1984 *
;* Last Modification: 09 July 1985 *
;***************************************
include scheme.equ
DGROUP group data
data segment word public 'DATA'
assume DS:DGROUP
data ends
PGROUP group prog
prog segment byte public 'PROG'
assume CS:PGROUP
;For space and performance reasons, some procedures have been written in the
; following style: the arguments are popped off the stack, and the
; procedure ends in an indirect JMP instead of a RET. In this source file,
; the following are such procedures:
; isspace, copybig
; Find approximate space left on stack
; Caling sequence: stkspc()
extrn _base:word
public stkspc
stkspc proc near
mov AX,SP
sub AX,DGROUP:_base
ret
stkspc endp
; Parse input integer
; Calling sequence: buildint(work,buf,base)
; Where ---- work: pointer to some workspace
; buf: pointer to integer characters
; base: numeric base
int_args struc
dw ? ;Caller's BP
dw ? ;Return address
bigptr dw ? ;Pointer to workspace
atptr dw ? ;Pointer to integer characters
bas dw ? ;Numeric base
int_args ends
public buildint
buildint proc near
push BP
mov BP,SP
cld ;Direction forward
mov SI,[BP].atptr ;Point DS:SI to characters
lodsb ;Fetch first character
cmp AL,'-' ;Negative?
pushf ;Save ZF
je negint ;Jump if negative
cmp AL,'+' ; or if signed positive
je negint
dec SI ;Point SI back to first char
negint: mov CX,1 ;At first, bignum is one word
add word ptr[BP].bigptr,3 ;Point BIGPTR to bignum proper
skiplp: lodsb ;Get first number char
cmp AL,'#' ;We know the base - skip all #x's
jne skipped ;All #x's skipped - parse number
inc SI ;Otherwise check again
jmp skiplp
biglp: lodsb ;Get next int character
skipped: mov DI,[BP].bigptr ;Point ES:DI to workspace
sub AL,'0' ;Character -> number
js bigend ;Jump if number ended
cmp AL,9 ;Jump if ordinary digit
jbe orddig
and AL,7 ;Otherwise, parse extra hex digit
add AL,9
orddig: xor AH,AH ;Clear AH
call bigx10 ;Multiply bignum by 10, adding digit
jmp biglp
bigend: sub DI,3 ;Point DI back to start of buffer
mov AX,CX ;Save integer size
stosw
xor AL,AL ;Clear AX
popf ;Get number's sign
jne stosgn ;Store it
inc AL
stosgn: mov [DI],AL
pop BP ;Restore BP
ret
;BIGX10: Multiply bignum at ES:[DI], size=CX words, by BASE and add AX
bigx10: push CX
mov DX,AX ;Transfer digit to add
cld
x10lp: mov AX,[DI] ;Get word to multiply
call wordx10 ;Multiply word by 10
stosw ;Replace result
loop x10lp ;Loop 'til done
pop CX ;Restore CX
or DX,DX ;Does a carry remain?
jz samlen ;Jump if not
mov ES:[DI],DX ;Otherwise, enlarge bignum
inc CX
samlen: ret
;WORDX10: Multiply AX by BASE and add DX; product in AX, carry in DX
wordx10: push CX ;Save value of CX
push DX ;Save carry in
mul word ptr[BP].bas ;Multiply by BASE
pop CX ;Restore carry to CX
add AX,CX ;Add carry
adc DX,0
pop CX ;Restore CX
ret
buildint endp
; Copy bignum data to a math buffer
; Calling sequence: copybig(pg,ds,buf)
; Where: pg,ds ---- page & displacement of bignum
; buf ------ pointer to math buffer
cb_args struc
dw ? ;Caller's BP
dw ? ;Return address
cbpg dw ? ;Page
cbds dw ? ;Displacement
cbbuf dw ? ;Buffer pointer
cb_args ends
public copybig
copybig proc near
pop BX ;Pop return address to BX
mov DX,DS ;Save DS in DX
pop SI ;Fetch logical page number
sal SI,1 ;Convert
LoadPage DS,SI ;Get page segment
;;; mov DS,DGROUP:pagetabl+[SI] ;Get page segment
pop SI ;Get displacement
mov AX,[SI]+1 ;Get size of bignum proper (words)
sub AX,4
shr AX,1
add SI,3 ;Point DS:SI to sign byte
pop DI ;Point ES:DI to math buffer
cld ;Direction forward
stosw ;Store bignum size in math buffer
movsb ;Copy sign byte
mov CX,AX ;Copy bignum proper
rep movsw
mov DS,DX ;Restore DS
jmp BX ;Return
copybig endp
; Convert buffered bignum to ASCII
; Calling sequence: big2asc(mathbuf,charbuf)
; Where: mathbuf --- pointer to buffered bignum
; charbuf --- pointer to ASCII charcater array
b2a struc
dw ? ;Caller's BP
dw ? ;Return address
mbuf dw ? ;Math buffer
cbuf dw ? ;Character buffer
b2a ends
public big2asc
big2asc proc near
push BP
mov BP,SP
mov SI,[BP].mbuf ;Fetch math buffer pointer
mov DI,[BP].cbuf ;Fetch character buffer pointer
cld ;Direction forward
lodsw ;Fetch bignum size
mov CX,AX
lodsb ;Fetch sign
test AL,1 ;Skip on positive bignum
jz posbig
mov AL,'-' ;First character: minus
stosb
posbig: mov BX,10 ;Set divisor to 10
and AX,1 ;Push 0 or 1 (1 if start with -)
prtbglp: push AX
call divbig ;Divide bignum by 10
mov AL,DL ;Store digit
add AL,'0'
stosb
pop AX ;Increment character counter
inc AX
or CX,CX ;Loop until bignum is zeroed
jnz prtbglp
mov CX,AX ;Transfer & save character count
push AX
sub DI,CX ;Point DI to beginning of string
call reverse ;Reverse digits in ASCII bignum
pop AX ;Restore character count
pop BP
ret
;Divide bignum at DS:SI, length CX words, by BX (ES=DS)
divbig: push CX ;Save count
push DI ;Save DI
add SI,CX ;Point SI to last word (most signif.)
add SI,CX
sub SI,2
cmp [SI],BX ;Will working length be reduced?
pushf
mov DI,SI ;ES:DI = DS:SI
std ;Direction backward
xor DX,DX ;Clear carry in
divlp: lodsw ;Fetch piece of dividend
div BX
stosw ;Store quotient (retain remainder)
loop divlp
add SI,2 ;Point SI again to first word
popf
pop DI
pop CX
jae divdone ;Jump if bignum length not reduced
dec CX
divdone: ret ;Remainder left in DX
;Reverse the string containing CX characters at ES:DI (ES=DS)
reverse: cmp byte ptr[DI],'-' ;Start with minus?
jne revpos ;No, reverse whole string
inc DI ;Otherwise, don't include minus in reverse
dec CX
revpos: mov SI,DI ;Point SI to last string char
add SI,CX
dec SI
shr CX,1 ;Number of switches
or CX,CX ;Jump if no switches to make
jz revend
revlp: mov AL,[DI] ;Exchange outside bytes
xchg AL,[SI]
stosb
dec SI ;Move pointers inward
loop revlp
revend: ret
big2asc endp
; Is character a whitespace?
; Calling sequence: isspace(ch)
; Where ch = character to check
; Returns zero iff not a whitespace
; NOTE: Before use, the C macro ISSPACE must not be defined
isspargs struc
dw ? ;Return address
issparg dw ? ;Argument
isspargs ends
public isspace
isspace proc near
pop DI ;Get return address
pop AX ;Get argument
cmp AL,' '
je issp
cmp AL,9
jb isntsp
cmp AL,13
jbe issp
isntsp: xor AX,AX ;Set to zero
issp: jmp DI ;Return
isspace endp
; Save stack pointer in case of abort
; Calling sequence: setabort()
; NOTE: Due to the program-sensitive nature of this routine, a call to
; SETABORT MUST be the very first in a C routine, and there must be
; NO preassigned local variables.
public setabort
setabort proc near
mov BX,SP ;Fetch stack pointer
mov SI,SS:[BX] ;Fetch return address
mov CL,CS:[SI-6] ;Fetch byte just before MOV BP,SP
cmp CL,55h ;Compare with PUSH BP opcode
je nolocal ;Jump if no extra stack space allocated
xor CH,CH ;Clear CH
add BX,CX ;Discount extra stack space
nolocal: add BX,2 ;Discount SETABORT's return address
mov DGROUP:abadr,BX ;Save pointer
ret
setabort endp
; Abort & set stack to saved pointer
; Calling sequence: abort(code)
; where: code ---- type of error message to print
public abort
abort proc
pop AX ;Discard return address (leaving CODE)
C_call errmsg ;Print error message
pop AX ;Get "value"
mov SP,DGROUP:abadr ;Restore stack for abort
pop BP ;Restore BP
ret ;Return (from aborted operation)
abort endp
prog ends
end