679 lines
23 KiB
NASM
679 lines
23 KiB
NASM
|
; =====> STIMER.ASM
|
|||
|
;***************************************
|
|||
|
;* TIPC Scheme '84 Things That Could *
|
|||
|
;* Have Been Done in C but Why Waste *
|
|||
|
;* Execution Time and Codespace? *
|
|||
|
;* *
|
|||
|
;* (C) Copyright 1984,1985 by Texas *
|
|||
|
;* Instruments Incorporated. *
|
|||
|
;* All rights reserved. *
|
|||
|
;* *
|
|||
|
;* Date Written: July 1985 *
|
|||
|
;* Last Modification: 8 October 1985 *
|
|||
|
;***************************************
|
|||
|
include scheme.equ
|
|||
|
|
|||
|
DGROUP group data
|
|||
|
data segment word public 'DATA'
|
|||
|
assume DS:DGROUP
|
|||
|
;Table of strange characters
|
|||
|
stranges db " ,'"
|
|||
|
db ';":()`'
|
|||
|
db 13,12,11,10,9,0
|
|||
|
|
|||
|
;Random number registers
|
|||
|
krala dw 22425
|
|||
|
kralb dw 30029 ;RANDOMIZE puts seed value here
|
|||
|
;Random number table
|
|||
|
kraltbl dw 4053,32361,7773,17385,11177,20413,27513,16501
|
|||
|
dw 5953,17673,20725,12247,28429,30861,16849,22375
|
|||
|
;Copy of random number registers and table.
|
|||
|
krala1 dw 22425
|
|||
|
kralb2 dw 30029
|
|||
|
kraltbl1 dw 4053,32361,7773,17385,11177,20413,27513,16501
|
|||
|
dw 5953,17673,20725,12247,28429,30861,16849,22375
|
|||
|
kral_len equ krala1-krala
|
|||
|
|
|||
|
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 may end in an indirect JMP instead of a RET. In this source file,
|
|||
|
; the following are such procedures:
|
|||
|
; toblock, gvchars, blk2pbuf, putlong, thefix, ldlong, msubstr,
|
|||
|
; mcmpstr, ldreg, pt_flds4, pt_flds6, str2str, adj4bord
|
|||
|
|
|||
|
; Convert flonum to bignum
|
|||
|
; Calling sequence: flotobig(flo,bigbuf)
|
|||
|
; Where ---- flo: double-length flonum such that abs(flo)>=1
|
|||
|
; bigbuf: pointer to buffer for bignum formation
|
|||
|
fbargs struc
|
|||
|
dw ? ;Return address
|
|||
|
flo dw ?,?,?,? ;Flonum
|
|||
|
bigbuf dw ? ;Pointer to bignum buffer
|
|||
|
fbargs ends
|
|||
|
public flotobig
|
|||
|
flotobig proc near
|
|||
|
mov BX,SP
|
|||
|
lea SI,[BX].flo ;Fetch pointer to flonum
|
|||
|
mov DI,[BX].bigbuf ;Fetch buffer pointer
|
|||
|
inc DI ;Point DI to sign byte
|
|||
|
inc DI
|
|||
|
cld ;Direction forward
|
|||
|
mov AX,[BX+6].flo ;Fetch exponent word to CX
|
|||
|
mov CX,AX
|
|||
|
and AX,0fh ;Save mantissa part back
|
|||
|
or AL,10h
|
|||
|
mov [BX+6].flo,AX
|
|||
|
mov AL,AH ;Zero AL
|
|||
|
test CH,80h ;Negative flonum?
|
|||
|
jz ftb1 ;Jump if not
|
|||
|
inc AL ;Otherwise, set AL to 1
|
|||
|
ftb1: stosb ;Store sign byte
|
|||
|
mov BX,DI ;Save address of first word in BX
|
|||
|
mov AL,AH ;Zero AL again
|
|||
|
and CX,7ff0h ;Discard sign byte and mantissa
|
|||
|
sub CX,3ff0h ;Remove exponent bias
|
|||
|
shl CX,1
|
|||
|
;At this stage, CH+1==number of bytes for bignum, CL shows how much to
|
|||
|
; shift mantissa left (once per 20h)
|
|||
|
mov DX,CX ;Use DX to count the shifts
|
|||
|
xor DH,DH ;Set up shift count
|
|||
|
add DX,80h ;Account for placing leading 1 in high byte
|
|||
|
ftb2: shl word ptr[SI],1 ;Shift mantissa left
|
|||
|
rcl word ptr[SI+2],1
|
|||
|
rcl word ptr[SI+4],1
|
|||
|
rcl word ptr[SI+6],1
|
|||
|
sub DX,20h ;Repeat until done
|
|||
|
jnz ftb2
|
|||
|
mov CL,CH ;Set CX to number of bignum bytes
|
|||
|
xor CH,CH
|
|||
|
inc CX
|
|||
|
sub CX,8 ;Check for leading zeros
|
|||
|
js ftb3 ;Jump if not all the mantissa will be done
|
|||
|
jz ftb3 ;Jump if no trailing zeros exist
|
|||
|
rep stosb ;Else store as many zeros as necessary
|
|||
|
ftb3: sub SI,CX ;Point SI to eligible part of mantissa
|
|||
|
add CX,8 ;Set mantissa byte count
|
|||
|
rep movsb ;Copy flonum mantissa to bignum
|
|||
|
mov CX,DI ;Find number of bytes in bignum proper
|
|||
|
sub CX,BX
|
|||
|
shr CX,1 ;Find number of words
|
|||
|
jnc ftb4 ;If a whole number of words, do nothing
|
|||
|
mov byte ptr[DI],0 ;Otherwise, pad with a 0
|
|||
|
inc CX ;Adjust word count
|
|||
|
ftb4: mov [BX-3],CX ;Save size of bignum
|
|||
|
ret
|
|||
|
flotobig endp
|
|||
|
|
|||
|
; Find the size of a flonum
|
|||
|
; Calling sequence: flosiz(flo);
|
|||
|
; Where ---- flo: double-length flonum
|
|||
|
; Returns the number of bytes needed for a working flonum formed from
|
|||
|
; trunc(flonum)
|
|||
|
fsargs struc
|
|||
|
dw ? ;Return address
|
|||
|
fl dw ?,?,?,? ;Double-length flonum
|
|||
|
fsargs ends
|
|||
|
public flosiz
|
|||
|
flosiz proc near
|
|||
|
mov SI,SP
|
|||
|
mov AX,[SI+6].fl ;Fetch word containing exponent
|
|||
|
and AX,7ff0h ;Drop sign and mantissa
|
|||
|
sub AX,3ff0h ;Is abs(flo) < 1?
|
|||
|
jc small ;Jump if small
|
|||
|
mov AL,AH ;Otherwise, return number of bytes
|
|||
|
xor AH,AH
|
|||
|
shl AL,1
|
|||
|
add AL,5
|
|||
|
ret
|
|||
|
small: xor AX,AX ;Return 0 for smallness
|
|||
|
ret
|
|||
|
flosiz endp
|
|||
|
|
|||
|
; Move bytes from buffer to allocated Scheme block
|
|||
|
; Calling sequence: toblock(reg,offs,buf,q)
|
|||
|
; Where ---- reg: Scheme register pointing to block
|
|||
|
; offs: Offset into block to begin transfer
|
|||
|
; buf: Buffer pointer
|
|||
|
; q: Number of bytes to move
|
|||
|
;Stack elements in order of popping:
|
|||
|
; Return address, register, offset, buffer address, number of bytes
|
|||
|
public toblock
|
|||
|
toblock proc near
|
|||
|
pop DX ;Save return address in DX
|
|||
|
pop BX ;Get register address
|
|||
|
mov DI,[BX].C_disp ;Put 8088 address in ES:DI
|
|||
|
mov BX,[BX].C_page
|
|||
|
mov AX,ES
|
|||
|
LoadPage ES,BX
|
|||
|
;;; mov ES,pagetabl+[BX]
|
|||
|
pop CX ;Get offset
|
|||
|
add DI,CX ;Add to DI
|
|||
|
pop SI ;Get source address (buffer ptr)
|
|||
|
pop CX ;Get number of bytes
|
|||
|
jcxz tbskip ;If no bytes, don't move
|
|||
|
cld ;Direction forward
|
|||
|
rep movsb ;Move bytes
|
|||
|
tbskip: mov ES,AX ;Restore ES
|
|||
|
jmp DX ;Return
|
|||
|
toblock endp
|
|||
|
|
|||
|
IFNDEF PROMEM
|
|||
|
; Give characters from a C string
|
|||
|
; Calling sequence: gvchars(str,len)
|
|||
|
; Where ---- str: C string address
|
|||
|
; len: Number of characters to give
|
|||
|
;Stack elements in order of popping:
|
|||
|
; Return address, string address, number of chars
|
|||
|
extrn givechar:near
|
|||
|
public gvchars
|
|||
|
gvchars proc near
|
|||
|
pop DI ;Get return address
|
|||
|
pop SI ;Get string address
|
|||
|
pop CX ;Get number of chars
|
|||
|
push DI ;Put return address back
|
|||
|
jcxz given ;If no chars, stop
|
|||
|
cld ;Direction forward
|
|||
|
gvlp: push CX ;Save count
|
|||
|
lodsb ;Fetch string character
|
|||
|
push SI ;Save pointer to next char
|
|||
|
push AX
|
|||
|
call givechar ;Give it
|
|||
|
inc SP ;Restore stack
|
|||
|
inc SP
|
|||
|
pop SI ;Restore address and count
|
|||
|
pop CX
|
|||
|
loop gvlp ;Give 'til done
|
|||
|
given: ret ;Return
|
|||
|
gvchars endp
|
|||
|
|
|||
|
; Move characters from block (symbol or string) to print buffer
|
|||
|
; Calling sequence: blk2pbuf(pg,ds,buf,len,ch,display)
|
|||
|
; Where ---- pg: logical page of the block
|
|||
|
; ds: block displacement
|
|||
|
; buf: address of print buffer
|
|||
|
; len: number of chars in the block
|
|||
|
; ch: character to escape (| for syms, " for strs)
|
|||
|
; display: whether to use escape characters
|
|||
|
; Returns the number 2n+s, where n is the number of characters in the
|
|||
|
; print buffer, and s=1 if strange chars were encountered, 0 otherwise.
|
|||
|
; Popping order: return address, pg, ds, buf, len, ch, display
|
|||
|
public blk2pbuf
|
|||
|
extrn hicases:byte
|
|||
|
blk2pbuf proc near
|
|||
|
pop DX ;Pop return address
|
|||
|
pop BX ;Pop page
|
|||
|
shl BX,1 ;Put segment of block in DS
|
|||
|
LoadPage DS,BX
|
|||
|
;;; mov DS,pagetabl+[BX]
|
|||
|
pop SI ;Pop block displacement
|
|||
|
pop DI ;Pop print buffer
|
|||
|
pop CX ;Pop character count
|
|||
|
pop BX ;Pop must-be-escaped character
|
|||
|
pop AX ;Pop whether to use escapes
|
|||
|
mov BH,AL ;Save escape boolean in BX
|
|||
|
and BH,7fh ;Save bit in BH for strangeness
|
|||
|
push DX ;Push return address
|
|||
|
push ES ; Save caller's ES register
|
|||
|
mov DX,DI ;Save start address of print buffer in DX
|
|||
|
jcxz zstrng ;If len=0, mark strangeness
|
|||
|
cmp BL,'"' ;Are we looking at a string?
|
|||
|
jne b2plp ;Skip if not
|
|||
|
zstrng: or BH,80h ;Otherwise, mark as strange
|
|||
|
jcxz done ;If len=0, forget everything else
|
|||
|
b2plp: lodsb ;Fetch char from block
|
|||
|
test BH,7fh ;Are we displaying escape chars?
|
|||
|
jz storit ;Jump if not
|
|||
|
cmp AL,BL ;Does the char need escaping?
|
|||
|
je escit ;If needed, do so
|
|||
|
cmp AL,'\'
|
|||
|
jne storit ;If not, just store it
|
|||
|
escit: mov AH,AL ;Save char in AH
|
|||
|
mov AL,'\' ;Store escape character
|
|||
|
stosb
|
|||
|
mov AL,AH ;Restore char
|
|||
|
storit: stosb ;Store it
|
|||
|
test BH,80h ;Do we already know that atom's strange?
|
|||
|
jnz skptest ;If so, don't bother testing
|
|||
|
push SI ;Else save SI
|
|||
|
mov SI,offset DGROUP:hicases ;Point SI to table of upper cases
|
|||
|
xchg BX,SI
|
|||
|
mov AH,AL ;Save char in AH
|
|||
|
xlat ES:hicases ;Fetch upper-case equivalent
|
|||
|
xchg BX,SI ;Restore BX
|
|||
|
cmp AH,AL
|
|||
|
jne mrkstrng ;If chars different, mark as strange
|
|||
|
mov SI,offset stranges ;Point SI to strange-character string
|
|||
|
strnglp: lods byte ptr ES:[SI] ;Fetch strange char
|
|||
|
or AL,AL ;End of string?
|
|||
|
jz notstrng ;Jump if so
|
|||
|
cmp AH,AL ;Is AH strange?
|
|||
|
jne strnglp ;If not, try again
|
|||
|
mrkstrng: or BH,80h ;Mark strange bit
|
|||
|
notstrng: pop SI ;Restore SI
|
|||
|
skptest: loop b2plp ;Repeat until done
|
|||
|
done: push ES ;Restore DS
|
|||
|
pop DS
|
|||
|
pop ES ; Restore caller's ES register
|
|||
|
mov byte ptr[DI],0 ;Put null at end of string
|
|||
|
mov AX,DI ;Return 2*(# of chars in string)+strangeness
|
|||
|
sub AX,DX
|
|||
|
shl BH,1
|
|||
|
rcl AX,1
|
|||
|
ret ;Return
|
|||
|
blk2pbuf endp
|
|||
|
ENDIF
|
|||
|
|
|||
|
; Load bignum block with long integer
|
|||
|
; Calling sequence: putlong(reg,longi)
|
|||
|
; Where ----- reg: register pointing to a bignum block
|
|||
|
; longi: 32-bit integer to store
|
|||
|
; Popping order: return address, register address, low & high integer words
|
|||
|
public putlong
|
|||
|
putlong proc near
|
|||
|
pop DX ;Fetch return address
|
|||
|
pop DI ;Fetch register address
|
|||
|
mov BX,[DI].C_page ;Point ES:DI to bignum block
|
|||
|
LoadPage ES,BX
|
|||
|
;;; mov ES,pagetabl+[BX]
|
|||
|
mov DI,[DI].C_disp
|
|||
|
add DI,3 ;Point ES:DI to block data area
|
|||
|
pop BX ;Put long integer in CX:BX
|
|||
|
pop CX
|
|||
|
xor AL,AL ;Sign byte - default positive
|
|||
|
test CH,80h ;Integer negative?
|
|||
|
jz poslong ;Jump if not
|
|||
|
inc AL ;Otherwise, set sign negative
|
|||
|
xor BX,-1 ;Negate long integer
|
|||
|
xor CX,-1
|
|||
|
add BX,1
|
|||
|
adc CX,0
|
|||
|
poslong: cld ;Direction forward
|
|||
|
stosb ;Store sign byte
|
|||
|
mov AX,BX ;Store least significant word
|
|||
|
stosw
|
|||
|
jcxz notlong ;If most signif. word=0, don't store it
|
|||
|
mov AX,CX
|
|||
|
stosw
|
|||
|
notlong: push DS ;Restore ES
|
|||
|
pop ES
|
|||
|
jmp DX ;Return
|
|||
|
putlong endp
|
|||
|
|
|||
|
|
|||
|
; Add word of zeros, if necessary, to bignum buffer
|
|||
|
; Calling sequence: thefix(buf)
|
|||
|
; Where ----- buf: address of bignum buffer
|
|||
|
; THEFIX is intended to alleviate a problem in the bignum division package.
|
|||
|
; Popping order: return address, buf
|
|||
|
public thefix
|
|||
|
thefix proc near
|
|||
|
pop DI ;Return address in DX
|
|||
|
pop SI ;Fetch bignum buffer address
|
|||
|
mov BX,[SI] ;Get bignum size in words
|
|||
|
inc BX ;Point BX+SI to last bignum byte
|
|||
|
shl BX,1
|
|||
|
test byte ptr[BX+SI],80h ;Is most signif. bit set?
|
|||
|
jz fixed ;If not, nothing to fix
|
|||
|
inc word ptr[SI] ;Otherwise, increase bignum size
|
|||
|
inc BX ;Add word of 0 to most significant end
|
|||
|
mov word ptr[BX+SI],0
|
|||
|
fixed: jmp DI ;Return
|
|||
|
thefix endp
|
|||
|
|
|||
|
|
|||
|
; Load a long integer value with a bignum
|
|||
|
; Calling sequence: ldlong(v, reg)
|
|||
|
; Where ----- v: pointer to a long integer
|
|||
|
; reg: register pointing to a bignum
|
|||
|
; Returns 0 if the load was successful, 1 otherwise
|
|||
|
; Popping order: return address, v, reg
|
|||
|
public ldlong
|
|||
|
ldlong proc near
|
|||
|
pop DX ;Pop return address
|
|||
|
pop DI ;Pop longint destination
|
|||
|
pop BX ;Pop register address
|
|||
|
push DS ;Save DS
|
|||
|
mov SI,[BX].C_disp ;Point DS:SI to bignum object
|
|||
|
mov BX,[BX].C_page
|
|||
|
LoadPage DS,BX
|
|||
|
;;; mov DS,pagetabl+[BX]
|
|||
|
cld ;Direction forward
|
|||
|
inc SI ;Put bignum length in CX
|
|||
|
lodsw
|
|||
|
mov CX,AX
|
|||
|
lodsb ;Put bignum sign in BL
|
|||
|
mov BL,AL
|
|||
|
cmp CX,6 ;Check size
|
|||
|
je big6
|
|||
|
cmp CX,8
|
|||
|
je big8
|
|||
|
mov AX,1 ;If here, bignum wrong size: error
|
|||
|
pop DS ;Restore DS
|
|||
|
jmp DX ;Return
|
|||
|
big6: lodsw ;Put bignum in CX:AX
|
|||
|
xor CX,CX
|
|||
|
jmp short havenum
|
|||
|
big8: lodsw ;Put bignum in CX:AX
|
|||
|
mov CX,AX
|
|||
|
lodsw
|
|||
|
xchg CX,AX
|
|||
|
havenum: test BL,1 ;Was bignum negative?
|
|||
|
jz storenum ;No, skip
|
|||
|
xor CX,-1 ;Otherwise, negate
|
|||
|
xor AX,-1
|
|||
|
add AX,1
|
|||
|
adc CX,0
|
|||
|
storenum: stosw ;Store to long integer
|
|||
|
mov AX,CX
|
|||
|
stosw
|
|||
|
xor AX,AX ;All's well
|
|||
|
pop DS ;Restore DS
|
|||
|
jmp DX ;Return
|
|||
|
ldlong endp
|
|||
|
|
|||
|
|
|||
|
; Move string bytes from one part of PCS memory to another
|
|||
|
; Calling sequence: msubstr(to_reg, from_reg, start, end)
|
|||
|
; Where ----- to_reg: register pointing to destination string
|
|||
|
; from_reg: register pointing to source string
|
|||
|
; start: offset at which to start copying
|
|||
|
; end: byte after the last to be copied
|
|||
|
; Popping order: return address, from_reg, to_reg, start, end
|
|||
|
public msubstr
|
|||
|
msubstr proc near
|
|||
|
pop DX ;Pop return address (temporarily)
|
|||
|
pop DI ;Pop destination register address
|
|||
|
pop SI ;Pop source register address
|
|||
|
pop AX ;Pop start index
|
|||
|
pop CX ;Pop end index
|
|||
|
push DS ;Save caller's DS & ES
|
|||
|
push ES
|
|||
|
mov BX,[DI].C_page ;Point ES:DI to destination object
|
|||
|
mov DI,[DI].C_disp
|
|||
|
LoadPage ES,BX
|
|||
|
;;; mov ES,pagetabl+[BX]
|
|||
|
add DI,BLK_OVHD ;Adjust DI past string overhead
|
|||
|
mov BX,[SI].C_page ;Point DS:SI to source object
|
|||
|
mov SI,[SI].C_disp
|
|||
|
LoadPage DS,BX
|
|||
|
;;; mov DS,pagetabl+[BX]
|
|||
|
add SI,BLK_OVHD ;Adjust SI past string overhead
|
|||
|
add SI,AX ;Point SI to start of substring
|
|||
|
sub CX,AX ;Set number of bytes to move
|
|||
|
cld ;Direction forward
|
|||
|
rep movsb
|
|||
|
pop ES ;Restore caller's DS & ES
|
|||
|
pop DS
|
|||
|
jmp DX ;Return
|
|||
|
msubstr endp
|
|||
|
|
|||
|
; Compare two Scheme bignums or strings for equal?-ness
|
|||
|
; Calling sequence: mcmpstr(reg1,reg2)
|
|||
|
; Where ----- reg1,reg2: registers pointing to objects to be compared
|
|||
|
; Returns 1 if the objects are equal?, 0 otherwise
|
|||
|
public mcmpstr
|
|||
|
mcmpstr proc near
|
|||
|
pop DX ;Pop return address
|
|||
|
pop SI ;Pop register addresses
|
|||
|
pop DI
|
|||
|
push DS ;Save caller's DS and ES
|
|||
|
push ES
|
|||
|
mov BX,[DI].C_page ;Point ES:DI to second object
|
|||
|
mov DI,[DI].C_disp
|
|||
|
LoadPage ES,BX
|
|||
|
;;; mov ES,pagetabl+[BX]
|
|||
|
mov BX,[SI].C_page ;Point DS:SI to the first object
|
|||
|
mov SI,[SI].C_disp
|
|||
|
LoadPage DS,BX
|
|||
|
;;; mov DS,pagetabl+[BX]
|
|||
|
mov CX,[SI].str_len ;Fetch byte count from source's length
|
|||
|
cmp CX,0 ;;; check for small string
|
|||
|
jge mcm_010
|
|||
|
add CX,BLK_OVHD+PTRSIZE
|
|||
|
mcm_010: xor AX,AX ;Default AX to FALSE
|
|||
|
cld ;Direction forward
|
|||
|
repe cmpsb ;Compare
|
|||
|
jne cmpskp ;If not equal, return FALSE
|
|||
|
inc AX ;Otherwise return TRUE
|
|||
|
cmpskp: pop ES ;Restore caller's ES and DS
|
|||
|
pop DS
|
|||
|
jmp DX ;Return
|
|||
|
mcmpstr endp
|
|||
|
|
|||
|
|
|||
|
; Load a register with a pointer from Scheme memory
|
|||
|
; Calling sequence: ldreg(reg,pg,ds)
|
|||
|
; Where ----- reg: register to be loaded
|
|||
|
; pg,ds: page and displacement of Scheme pointer
|
|||
|
; Popping order: return address, reg, pg, ds
|
|||
|
public ldreg
|
|||
|
ldreg proc near
|
|||
|
pop DX ;Pop return address
|
|||
|
pop DI ;Pop destination register
|
|||
|
pop BX ;Pop page and displacement
|
|||
|
pop SI
|
|||
|
mov CX,DS ;Save caller's DS
|
|||
|
shl BX,1 ;Point DS:SI to Scheme pointer
|
|||
|
LoadPage DS,BX
|
|||
|
;;; mov DS,pagetabl+[BX]
|
|||
|
cld ;Direction forward
|
|||
|
lodsb ;Load register's page field
|
|||
|
xor AH,AH
|
|||
|
mov ES:[DI].C_page,AX
|
|||
|
lodsw ;Load displacement field
|
|||
|
mov ES:[DI].C_disp,AX
|
|||
|
mov DS,CX ;Restore caller's DS
|
|||
|
jmp DX ;Return
|
|||
|
ldreg endp
|
|||
|
|
|||
|
|
|||
|
; Generate pseudorandom numbers in the range 0-16,383
|
|||
|
;
|
|||
|
; Author: John C. Jensen (converted to assembly lang. by Mark Meyer)
|
|||
|
; Date Written: 9 January 1985
|
|||
|
; Last Modification: 9 July 1985
|
|||
|
;
|
|||
|
; Calling Sequence: krandom()
|
|||
|
;
|
|||
|
; Note: the following random number generator is due to Jaroslav
|
|||
|
; Kral. It was adapted to 16 bit words and proven both efficient
|
|||
|
; and statistically satisfactory by Overstreet and Nance of SMU.
|
|||
|
; See Karl's paper for initialization values for other word
|
|||
|
; lengths.
|
|||
|
;
|
|||
|
; -- Kral, Jaroslav. "A New Additive Pseudorandom Number
|
|||
|
; Generator for Extremely Short Word-Lengths," Information
|
|||
|
; Processing Letters, 1 (1972), 164-167 (erratum noted in 1
|
|||
|
; (1972), 216).
|
|||
|
;
|
|||
|
; -- Overstreet, C. and Nance, R.E., "A Random Number Generator
|
|||
|
; for Small Word-Length Computers," Proceedings of the ACM '73
|
|||
|
; Conference, p. 219-223.
|
|||
|
;
|
|||
|
public krandom
|
|||
|
krandom proc near
|
|||
|
mov AX,krala ;Put old KRALA in AX, old KRALB in BX
|
|||
|
mov BX,kralb
|
|||
|
mov CX,BX ;KRALC = KRALB
|
|||
|
add BX,AX ;KRALB = (KRALA+KRALB) mod 2^n
|
|||
|
and BH,3fh ; (Currently, n=14)
|
|||
|
mov kralb,BX
|
|||
|
mov BL,BH ;J = KRALB / 2^(n-4)
|
|||
|
shr BL,1
|
|||
|
and BX,01eh
|
|||
|
mov AX,[BX]+offset kraltbl ;KRALA = KRALTBL[J]
|
|||
|
mov krala,AX
|
|||
|
add AX,CX ;KRALTBL[J] = (KRALA+KRALC) mod 2^n
|
|||
|
and AH,3fh
|
|||
|
mov [BX]+offset kraltbl,AX
|
|||
|
ret ;Return KRALTBL[J]
|
|||
|
krandom endp
|
|||
|
|
|||
|
; RANDOMIZE - Reset the random number registers and table back to their
|
|||
|
; original values, then put the seed value into "kralb".
|
|||
|
; Calling sequence: randomize(seed) ;seed = normal C int
|
|||
|
public randomiz
|
|||
|
randz_args struc
|
|||
|
dw ? ;caller's ES
|
|||
|
dw ? ;caller's BP
|
|||
|
dw ? ;return address
|
|||
|
rseed dw ? ;argument 1 (seed)
|
|||
|
randz_args ends
|
|||
|
randomiz proc near
|
|||
|
push BP ;save caller's BP
|
|||
|
push ES ;save ES
|
|||
|
mov BP,SP ;establish local addressability
|
|||
|
mov AX,DS ;copy DS to ES
|
|||
|
mov ES,AX
|
|||
|
mov CX,kral_len/2 ;restore random state to its original state
|
|||
|
lea SI,krala1
|
|||
|
lea DI,krala
|
|||
|
rep movsw
|
|||
|
mov BX,[BP].rseed ;get seed
|
|||
|
cmp BX,0 ;is it zero?
|
|||
|
jnz randz_1 ;no, jump; use the seed directly
|
|||
|
mov AX,2C00h ;get the time from DOS
|
|||
|
int 21h
|
|||
|
push DX ;tempsave DX (seconds, hundredths)
|
|||
|
xor AX,AX
|
|||
|
mov AL,CH ;determine #sec-in-hours
|
|||
|
mov DX,3600
|
|||
|
mul DX
|
|||
|
mov BX,AX
|
|||
|
xor AX,AX
|
|||
|
mov AL,CL ;determine #sec-in-minutes
|
|||
|
mov DX,60
|
|||
|
mul DX
|
|||
|
add BX,AX ;#sec-in-hours + #sec-in-minutes
|
|||
|
pop DX ;restore seconds (and hundredths, but ignore it)
|
|||
|
xchg DH,DL
|
|||
|
mov DH,0
|
|||
|
add BX,DX ;add in seconds
|
|||
|
randz_1: mov kralb,BX ;set seed
|
|||
|
pop ES ;wrap up
|
|||
|
pop BP
|
|||
|
ret
|
|||
|
randomiz endp
|
|||
|
|
|||
|
|
|||
|
; Set the cdr field of a list cell
|
|||
|
; Calling sequence: asetcdr(creg, preg)
|
|||
|
; Where ---- creg: register pointing to cell
|
|||
|
; preg: register holding new pointer
|
|||
|
; Popping order: Return address, destination register, pointer register
|
|||
|
public asetcdr
|
|||
|
asetcdr proc near
|
|||
|
pop DX ;Pop return address
|
|||
|
pop DI ;Pop address of register
|
|||
|
mov CX,ES ;Save caller's ES
|
|||
|
mov BX,[DI].C_page ;Point ES:DI to list cell
|
|||
|
mov DI,[DI].C_disp
|
|||
|
LoadPage ES,BX
|
|||
|
;;; mov ES,pagetabl+[BX]
|
|||
|
add DI,PTRSIZE ;Adjust for cdr field
|
|||
|
pop SI ;Pop address of pointer
|
|||
|
cld ;Direction forward
|
|||
|
mov AX,[SI].C_page ;Store into cdr field
|
|||
|
stosb
|
|||
|
mov AX,[SI].C_disp
|
|||
|
stosw
|
|||
|
mov ES,CX ;Restore ES
|
|||
|
jmp DX ;Return
|
|||
|
asetcdr endp
|
|||
|
|
|||
|
|
|||
|
; Get field values from a port object
|
|||
|
; Calling sequence: pt_flds4(reg, &ull, &ulc, &nl, &nc)
|
|||
|
; pt_flds6(reg, &cl, &cc, &ull, &ulc, &nl, &nc)
|
|||
|
; Where ----- reg: register pointing to port
|
|||
|
; cl: variable to receive CUR_LINE value
|
|||
|
; cc: ... CUR_COL value
|
|||
|
; ull: ... UL_LINE value
|
|||
|
; ulc: ... UL_COL value
|
|||
|
; nl: ... N_LINES value
|
|||
|
; nc: ... N_COLS value
|
|||
|
; Warning: This routine expects these six fields to be contiguous
|
|||
|
; Popping order: return address, reg, (&cl, &cc,) &ull, &ulc, &nl, &nc
|
|||
|
public pt_flds4,pt_flds6
|
|||
|
pt_flds proc near
|
|||
|
pt_flds6: mov CX,pt_cline ;Set CX to offset of first field
|
|||
|
jmp fldsmrg
|
|||
|
pt_flds4: mov CX,pt_ullin ;Set CX to offset of first field
|
|||
|
fldsmrg: pop DX ;Pop return address
|
|||
|
mov AX,DS ;Save caller's DS
|
|||
|
pop BX ;Pop register address
|
|||
|
mov SI,[BX].C_disp ;Point DS:SI to first field
|
|||
|
mov BX,[BX].C_page
|
|||
|
LoadPage DS,BX
|
|||
|
;;; mov DS,pagetabl+[BX]
|
|||
|
add SI,CX
|
|||
|
cld ;Direction forward
|
|||
|
sub CX,pt_cline ;Set CX to number of fields to do
|
|||
|
shr CX,1 ; (6 - (1/2)(CX - pt_cline))
|
|||
|
neg CX
|
|||
|
add CX,6
|
|||
|
fldslp: pop DI ;Pop destination variable address
|
|||
|
movsw ;Transfer value
|
|||
|
loop fldslp ;Repeat until done
|
|||
|
mov DS,AX ;Restore DS
|
|||
|
jmp DX ;Return
|
|||
|
pt_flds endp
|
|||
|
|
|||
|
; Copy bytes from one C location to another
|
|||
|
; Calling sequence: str2str(dest_adr, src_adr, n)
|
|||
|
; Where ----- dest_adr: destination address
|
|||
|
; src_adr: source address
|
|||
|
; n: number of bytes to copy
|
|||
|
; Popping order: return address, dest_adr, src_adr, n
|
|||
|
public str2str
|
|||
|
str2str proc near
|
|||
|
pop DX ;Pop return address
|
|||
|
pop DI
|
|||
|
pop SI
|
|||
|
pop CX
|
|||
|
cld ;Direction forward
|
|||
|
rep movsb ;Copy bytes
|
|||
|
jmp DX ;Return
|
|||
|
str2str endp
|
|||
|
|
|||
|
; Adjust window region variables for presence of a border
|
|||
|
; Calling sequence: adj4bord(&ull, &nl, &ulc, &nc)
|
|||
|
; Where ----- ull: Upper-left-line variable
|
|||
|
; nl: Number-of-lines variable
|
|||
|
; ulc: Upper-left-column variable
|
|||
|
; nc: Number-of-columns variable
|
|||
|
; Popping order: return address, &ull, &nl, &ulc, &nc
|
|||
|
public adj4bord
|
|||
|
max_lines equ 25
|
|||
|
max_cols equ 80
|
|||
|
adj4bord proc near
|
|||
|
pop DX ;Pop return address
|
|||
|
mov BX,max_lines ;Expand HEIGHT of window region
|
|||
|
expand: pop SI ;Pop upper-left parameter
|
|||
|
pop DI ;Pop extent parameter
|
|||
|
mov AX,[SI] ;Get value of upper-left parm
|
|||
|
or AX,AX ;If zero,
|
|||
|
jz expand1 ; skip next two instructions
|
|||
|
dec word ptr[SI] ;Else, expand backward
|
|||
|
inc word ptr[DI]
|
|||
|
dec AX ;Adjust AX to match upper-left parm
|
|||
|
expand1: add AX,[DI] ;Find opposite edge
|
|||
|
cmp AX,BX ;If edge too far,
|
|||
|
jae expand2 ; skip next instruction
|
|||
|
inc word ptr[DI] ;Else, expand forward
|
|||
|
expand2: cmp BX,max_cols ;If we're finished,
|
|||
|
je adjex ; jump out
|
|||
|
mov BX,max_cols ;Else, expand WIDTH of window region
|
|||
|
jmp expand
|
|||
|
adjex: jmp DX ;Return
|
|||
|
adj4bord endp
|
|||
|
|
|||
|
prog ends
|
|||
|
end
|
|||
|
|