📄 nhstutil.asm
字号:
; stack and will be lost at exit. The string will be transferred
; to a temp just before the sd is trashed. It is guaranteed that
; b$curlevel will be adjusted appropriately before this routine
; is called. If the SD is 0 length, a ptr to b$nuldes will be returned.
;Entry:
; psdOwner - pointer to sd currently owning string.
;Exit:
; AX - pointer to temp sd that is new owner of string
; (b$nuldes if 0 length).
;Uses:
; Per convention.
;Exceptions:
; B$ERR_ST if no temps are left.
;****
cProc B$STMakeTemp,<PUBLIC,FAR>
parmW psdOwner
cBegin
XOR AX,AX
CMP WORD PTR[TMPHDR],AX ;are there any temps left
JZ TEMPOV ;brif not - error out
MOV BX,[psdOwner]
CMP [BX],AX ;is this a null (0-length) string?
JNZ NotNullstr ;brif not
MOV AX,OFFSET DGROUP:b$nuldes ;get ptr to b$NulDes
JMP SHORT BSTMakeTempX ;return it in ax
NotNullStr:
cCall MakeTemp ;call near routine to do the work
XCHG AX,BX ;return new sd in AX
BSTMakeTempX:
cEnd
cProc MakeTemp,<NEAR>
cBegin <nogen>
PUSH SI ;preserve SI
PUSH [BX] ;push size of string
MOV BX,[BX+2] ;[BX] = ptr to string data
JMP SHORT ALCTMP ;jump to common code to make the temp
;the new owner
cEnd <nogen>
PAGE
;***
; B$STCHKTMP - Check for temporary string descriptor
; Function:
; Check to see if the string descriptor is a temporary.
; Inputs:
; BX = Address of string descriptor
; Outputs:
; Carry flag set if a temp
; Carry clear in not
; Modifies:
; None
; Exceptions:
; None
;****
B$STCHKTMP: ;[C1]
CMP BX,OFFSET DGROUP:TMPH
JNC RETL ;If above high end, not a temp
CMP BX,OFFSET DGROUP:TMPL
CMC
RET
PAGE
;***
; B$STGETSTRLEN - get string length
; Purpose:
; Computes the byte length of a zero-terminated ASCII string.
;
; Inputs:
; BX = offset of string
; Outputs:
; AX = Length of the line (not including 00)
; Modifies:
; None.
; Exceptions:
; None.
;****
B$STGETSTRLEN:
PUSH ES
PUSH DS
POP ES ;Set ES = DS
PUSH CX
PUSH DI
MOV CX,-1 ;Scan up to 65535 characters
MOV AL,0 ;Search for a zero
MOV DI,BX
REPNE SCASB ;Scan for a 00
MOV AX,CX ;Amount of the 65535 left
NOT AX
DEC AX
POP DI
POP CX
POP ES
RET
PAGE
;***
;B$STALCTMPCPY - Allocate a temp string copy.
;DBCS-callback
;
;Purpose:
; Allocate a temporary string of the length specified. Copy the
; data from the string whose descriptor was passed to the new string.
; Does not deallocate the original string.
;
;Inputs:
; BX = Length of string to copy.
; DX = Address of string data to copy
;
;Outputs:
; BX = Address of temp string descriptor
;
;Uses:
; Per Convention
;
;Preserves:
; AX, CX
;
;Exceptions:
; None
;****
B$STALCTMPCPY: ;[C1]
PUSH ES
PUSH DS
POP ES ;Set ES = DS
PUSH CX
MOV CX,BX ;Get length in CX
PUSH SI
MOV SI,DX ;Point to source of string data
CALL B$STALCTMP ;[C1]Get a temporary string of the right length
PUSH DI
MOV DI,DX ;String data destination
MOV DX,SI ;Restore DX
INC CX ;Round up if odd
SHR CX,1 ;Move by words
REP MOVSW
POP DI
POP SI
POP CX
POP ES
RET
PAGE
;***
; B$STDALCALLTMP - Deallocate all temporary strings
; Purpose:
; Free all temporary strings and descriptors which were
; allocated at or above the specified level.
;
; Inputs:
; AX = program level at or above which temporary strings
; will be deallocated. Use 0 (the minimum level) to
; deallocate ALL temporary strings.
; Outputs:
; None.
; Modifies:
; None.
; Exceptions:
; None.
;****
B$STDALCALLTMP: ;[C1]
PUSH BX
MOV BX,OFFSET DGROUP:TMPL ;First string descriptor
DTSLOOP:
CMP WORD PTR[BX+4],AX ;string allocation level >= specified
JL NEXTMP ;skip if not
CALL DELTMP ;otherwise delete it
NEXTMP:
ADD BX,LENTEMP ;Next temp descriptor
CMP BX,OFFSET DGROUP:TMPH ;Done yet?
JB DTSLOOP
POP BX
RETL:
RET
PAGE
;***
;B$STDALCTMP - Deallocate if temporary string
;DBCS-callback
;
;Purpose:
; Check to see if the descriptor is a temporary one.
; If so, deallocate its string data and release the descriptor
; for future use.
;
;Inputs:
; BX = Address of string descriptor
;
;Outputs:
; None.
;
;Uses:
; Per Convention
;
;Preserves:
; AX, BX, CX, DX
;
;Exceptions:
; None.
;****
B$STDALCTMP: ;[C1]
CALL B$STCHKTMP ;[C1]See if temp string
JNC RETL ;If not, leave it
DELTMP:
CALL B$STDALC ;[C1]Free the space
;***
; B$STDALCTMPDSC - deallocate temporary descriptor
; Purpose:
; Deallocate the temporary string descriptor pointed by BX and
; relink it in the temporary descriptor chain for subsequent
; allocation.
;
; Inputs:
; BX = address of temporary string descriptor
; Outputs:
; None.
; Modifies:
; None.
; Exceptions:
; None.
;****
B$STDALCTMPDSC:
; Make sure that we do not attempt to deallocate a temp twice
DbAssertRel [BX+4],NZ,-1,NH_TEXT,<Attempted to dealloc an already dealloced string temp>
PUSH AX
MOV AX,BX
XCHG AX,[TMPHDR] ;Make this one the first free
MOV [BX],AX ;Set link to former first one
; MOV WORD PTR[BX+2],-1 ;Make it easy to see its free
MOV WORD PTR[BX+4],-1 ; < min level (0) means free temp desc
POP AX
RET
PAGE
;***
;B$STALCTMPSUB - Allocate temporary substring copy
;DBCS-callback
;
;Purpose:
; Create a temporary string and copy the specified portion of the given
; string into it. The given string is deleted if it is a temp.
;
; The starting position in the string is specified as an offset from
; the beginning of the string. Thus 0 <= CX <= Len(BX)-DX
;
;Inputs:
; BX = Address of string descriptor
; CX = Starting position within string
; DX = Length
;
;Outputs:
; BX = Address of temp string descriptor
;
;Uses:
; Per Convention
;
;Preserves:
; AX, CX, DX
;
;Exceptions:
; None.
;****
B$STALCTMPSUB: ;[C1]
PUSH ES
PUSH DS
POP ES ;Set ES = DS
PUSH AX ;Save registers
PUSH CX
PUSH SI
PUSH DI
MOV SI,CX ;SI = offset into string
MOV AX,BX ;AX = source string descriptor
MOV CX,DX ;CX = length
MOV BX,DX ;BX = length
CALL B$STALCTMP ;[C1]Allocate temp string
MOV DI,DX ;DI = temp string contents address
XCHG AX,BX ;AX = temp string descriptor
;BX = source string descriptor
ADD SI,[BX+2] ;add in old string contents address
CALL B$STDALCTMP ;[C1]delete old temp string
XCHG AX,BX ;BX = new string descriptor
MOV DX,CX ;get length back in DX to leave it unchanged
INC CX ;if odd, round up to even
SHR CX,1 ;bytes to words
REP MOVSW ;move into temp string
POP DI
POP SI
POP CX
POP AX
POP ES
RET
PAGE
;***
; B$STDALC - Deallocate string
; Purpose:
; Deallocate the string data pointed by the string descriptor.
;
; Inputs:
; BX = Address of string descriptor.
; Outputs:
; None.
; Modifies:
; None.
; Exceptions:
; None.
;****
B$STDALC: ;[C1]
PUSH ES
PUSH DS
POP ES ;Set ES = DS
PUSH AX ;save register
XOR AX,AX ;clear to set flag for deletion
CALL B$STADJ ;call routine for string data deallocation
POP AX ;restore register
POP ES
RET ;return to caller
PAGE
;***
; B$STADJ - deallocate/adjust string data
; Function:
; Deallocates or adjusts the string data pointed by the
; string descriptor in BX. If AX=0, the data is deallocated.
; If AX<>0, the string backpointer is adjusted by the value
; of AX.
;
; Inputs:
; AX = adjustment value
; AX=0 - deallocate string.
; AX<>0 - adjust string backpointer.
; BX = Address of string descriptor.
; DS = segment that heap is in
; ES = segment that state vars are in
; Outputs:
; None.
; Modifies:
; None.
; Exceptions:
; None.
;****
assumes ES,DGROUP
assumes DS,NOTHING
B$STADJ:
CMP WORD PTR [BX],0 ; is string allocated?
JZ ADJSTR_EXIT ; brif not
PUSH CX ;save register
PUSH SI
MOV SI,[BX+2] ;Get pointer to string data
; Test if string is in string space - from [b$STRING_FIRST] to
; [b$STRING_END].
CMP SI,ES:[b$STRING_FIRST] ;test if before string space
JB ADJSTR_RETURN ;if less, then constant, do not deallocate
CMP SI,ES:[b$STRING_END] ;test if after string space
JA ADJSTR_FIELDED ;if more, then fielded string, jump
; String is in string space. First adjust the backpointer by AX.
; Then test if deallocation is requested and, if so, replace
; backpointer with free string header with <data length>+1.
ADD [SI-2],AX ;adjust backpointer of string
OR AX,AX ;test if deallocation was requested
JNZ ADJSTR_RETURN ;if so, then finished, jump
MOV CX,[BX] ;Get length of string to free
INC CX ;Round up if odd
OR CL,1 ;And set free bit
XCHG CX,[SI-2] ;Get backpointer and set free length
CMP CX,BX ;Check backpointer
JE ADJSTR_RETURN ;if equal, then just return
PUSH ES ;force DS = ES incase of CHAIN
POP DS ;sets up DS = BASIC DS
JMP B$ERR_SSC ;jump to error routine
; String is in the local heap, probably a fielded string.
; Call routine to delete descriptor from the appropriate heap
; entry backpointer string.
ADJSTR_FIELDED:
CALL B$LHFLDDESCADJ ;delete descriptor in BX for heap entry
ADJSTR_RETURN:
POP SI ;restore registers
POP CX
ADJSTR_EXIT:
RET ;return to caller
assumes DS,DGROUP
assumes ES,NOTHING
PAGE
;***
; B$STPUTZ - Put zero at end of string
;
; Inputs:
; BX = Address of string descriptor
; Function:
; Make into a string with a zero byte on the end. If length is presently
; odd, just jam a zero into the extra byte. If even, create a temp
; one byte longer and put the zero there.
; Outputs:
; BX = Address of string descriptor
; Registers:
; Only BX and F affected.
;****
B$STPUTZ:
PUSH DX
MOV DX,[BX]
PUSH CX
XOR CX,CX ;Offset = 0
INC DX ;Length = old length + 1
CALL B$STALCTMPSUB ;[C1]Always copy string into string space
DEC DX
POP CX
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -