📄 nhlhcore.asm
字号:
TITLE NHLHCORE - Core Local Heap utilities
;***
;NHLHCORE - Core Local Heap utilities
;
; Copyright <C> 1987, Microsoft Corporation
;
;Purpose:
; This module contains the core local heap utilities that are required to
; support /O programs which use string space and simple OPEN statements. Field
; manipulations and additional CHAIN support is elsewhere.
;
;******************************************************************************
;
; Near Heap Support
;
; The near heap support code deals with three pieces:
;
; Local Heap - Contains FDBs & Dynamic (small) arrays & QBI tables
; String Space - Strings and FIELDed string entries
; Variable Heap - Interpeter Only, value tables
;
; In memory, the heaps, associated variables and stack are layed out as
; follows:
;
; High Memory (DGROUP)
;
; +--+--+--+--+--+--+--+--+
; b$HEAP_FIRST --> | | odd: last useable physical
; +--+--+--+--+--+--+--+--+ byte of Heap
; b$NH_last --> | | even: last useable physical
; \ \ word of Heap
; Local Heap
; \ \
; | |
; +--+--+--+--+--+--+--+--+
; b$HEAP_END --> | LH_END Constant | odd: ?
; +--+--+--+--+--+--+--+--+
; | |
; + +
; b$STRING_END --> | | even: word containing 0xFFFF
; \ \
; String Space
; b$NH_First -\ \ \
; b$STRING_FIRST --\--> | | first useable byte/word
; +--+--+--+--+--+--+--+--+ \
; b$HEAP_FIRST_SWAP --> | | \
; \ \ \
; Variable Heap Interpeter Only
; \ \ /
; b$HEAP_END_SWAP --> | | /
; +--+--+--+--+--+--+--+--+ /
; | |
; + +
; __atopsp --> | | last useable word of stack
; \ \
; Stack
; \ \
; b$pend --> | | first useable word of stack
; +--+--+--+--+--+--+--+--+
;
;==============================================================================
;
;
; Heap Entry:
;
; +--+--+--+--+--+--+--+--+ High memory
; Pointer to entry --> | Entry Type Byte |
; +--+--+--+--+--+--+--+--+
; | File #, if applicable |
; +--+--+--+--+--+--+--+--+
; | |
; + Total Entry Size +
; | |
; +--+--+--+--+--+--+--+--+
; | Back Pointer |
; + (Pointer to +
; | owner pointer) |
; +--+--+--+--+--+--+--+--+
; | (offset part of sd |
; + for fielded string +
; | if applicable) |
; +--+--+--+--+--+--+--+--+
; | (length part of sd |
; + for fielded string +
; | if applicable) |
; +--+--+--+--+--+--+--+--+
; | |
; \ \
; Data
; \ \
; Start of Data --> | |
; +--+--+--+--+--+--+--+--+
; | |
; + Total Entry Size +
; | (Same as in header) |
; +--+--+--+--+--+--+--+--+ Low memory
;
; The pointer to an entry normally points to the type byte in the header; since
; length of the entry (hdr + data + trailer length word) is kept at the start
; and the end of the block, it is easy to access; subtract that length from the
; current entry pointer, and it will be pointing to the same place in the next
; hdr - - - yes, since the heap grows down, subtracting from the pointer moves
; you "forward" in the heap. Heap entries can be of any even-byte size; headers
; are 6 bytes in length, except for fdb's, which have 10-byte headers.
;
;==============================================================================
;
; Internal structure of (simple) fielded strings.
;
; FDB:
;
; /--+-----------------------+--/ /--+---------------+--/ /--+-------+
; | Field Buffer | | String Desc | |LH_FILE|
; /--+-----------------------+--/ /--+------------+--+--/ /--+-------+
; ^ ^ ^ ^ |
; | | | | |
; Individual | | +-----------+ | |
; Static | | | | |
; String | +-------+ | | |
; Descriptors: | | | | |
; | | | | |
; +-------+ +-------+ +-------+ | |
; | SD | | SD | | SD | | |
; +-------+ +-------+ +-------+ | |
; ^ ^ ^ | |
; Fielded | | | | |
; String +----+ ++ +--+ | |
; BackPointer | | | | |
; String: | | | | |
; | | | | |
; +---------------------------------+ |
; | | | | |
; | +----------------------------------+
; | \/ | | |
; +---+---+----+--+----+--+----+--+--/
; | BkPtr | SD Ptr| SD Ptr| SD Ptr|
; +-------+-------+-------+-------+--/
;
; In summary, the FDB contains a string descriptor which references a string
; (the fielded string backpointer string) containing pointers to several string
; descriptors. These string descriptors (static, in this example) reference
; locations in the FIELD buffer in the FDB, and define the position and length
; of the individual FIELDs.
;
; The backpointer string can grow as additional FIELD statements are executed,
; and can shrink at CHAIN time. Since it is a string, it is also subject to
; movement as string-space compaction occurs. The compaction code must be
; sensitive to the pointers involved in such movement.
;
; When the fielded strings are defined in a static string array, operation is
; essentially the same as individual static strings. The static SD's do not
; move, and dereferencing performed by any calling code looks exactly like
; static individual SD's.
;
;
; Internal structure of fielded strings in dynamic arrays.
;
; FDB:
;
; /--+-----------------------+--/ /--+---------------+--/ /--+-------+
; | Field Buffer | | String Desc | |LH_FILE|
; /--+-----------------------+--/ /--+------------+--+--/ /--+-------+
; ^ ^ ^ ^ |
; | | | | +------------------+
; Array of | | +---+ | |
; String | | | +---------------------+ |
; Descriptors: | +---+ | | |
; | | | | |
; +------++------++------++--/ /--+-------+--/ /--+-------+ | |
; | SD | SD | SD | | BkPtr | |LH_ARRA| | |
; +-------+-------+-------+--/ /--+-----+-+--/ /--+-------+ | |
; ^ ^ ^ | | |
; Fielded | | | | | |
; String +-----+ +-----+ +-----+ +----+ | |
; BackPointer ^ | | | | | |
; String: +-----|-------|-------|----------+ | | |
; | | | | | | |
; +-------------------------------------------------------+ |
; | | | | | | |
; | +-----------------------------------------------------+
; | \/ | | | | |
; +---+---+----+--+----+--+----+--+--/ | |
; | BkPtr | SD Ptr| SD Ptr| SD Ptr| | |
; +-------+-------+-------+-------+--/ | |
; | |
; String +------------------------------+ |
; Array | |
; Descriptor: | +---------------------------+
; | \/
; ++------+--/
; |DatPtr |
; +-------+--/
;
;
; The added complication of dynamic fielded string arrays is that the string
; descriptors live in the local heap, and hence can move, in addition to the
; backpoint string, which lives in string space and can also move. Both LH and
; SS code must update pointers appropriately.
;
;==============================================================================
INCLUDE switch.inc
INCLUDE baslibma.inc
INCLUDE files.inc
INCLUDE rmacros.inc
USESEG _DATA
USESEG _BSS
USESEG NH_TEXT
INCLUDE seg.inc
INCLUDE nhutil.inc ;for heap definitions
INCLUDE idmac.inc
INCLUDE array.inc ;for array definitions
sBegin _BSS
externW b$STRING_END ;defined in NHSTUTIL.ASM
externW b$STRING_FREE ; defined in NHSTUTIL.ASM
externW b$NH_first ;defined in NHINIT.ASM
externW b$PTRFIL ;defined in GLOBAL.INC
;NOTE: Variable Heap support code requires next 4 data items be contiguous [23]
globalW b$HEAP_FIRST,,1 ;heap start pointer
globalW b$HEAP_FREE,,1
globalW b$HEAP_END,,1
globalW b$P_HEAP_GROW,,1
;NOTE: Variable Heap support code requires next 4 data items be contiguous [23]
globalW b$HEAP_FIRST_SWAP,,1
globalW b$HEAP_FREE_SWAP,,1
globalW b$HEAP_END_SWAP,,1
staticW P_HEAP_GROW_SWAP,,1
globalW b$fVarHeapActive,,1 ; non-0 when variable heap
; is active
sEnd _BSS
sBegin _DATA
globalW b$pFHRaiseBottom,Near_Ret,1 ;vector for B$FHRaiseBottom
globalB b$Clearing,0,1 ; CLEAR statement in process flag
sEnd _DATA
externFP B$ULDataRelease ;releases ul Data images
externFP CompressHelp
sBegin NH_TEXT
ASSUMES CS,NH_TEXT
PUBLIC B$LHNXTFIL ; find next file entry in heap
PUBLIC B$LHADJ ;adjust heap entry
PUBLIC B$LHDALC ;deallocate heap entry
PUBLIC B$LHFLDDESCADJ ; delete/adjust descriptor in backpointer string
PUBLIC B$LHDALCALLFLD ; deallocate all fielded strings from heap entry
PUBLIC B$LHSetFree ;set free heap entry pointer
PUBLIC B$LH_ALC_FREE ;[ln]
PUBLIC B$LH_PTR_FROM_DATA
PUBLIC B$LH_CPCT
PUBLIC B$LH_FROM_SS ;[ln]
PUBLIC B$LH_PTR_CHECK ;[ln] check entry at [SI] for consistency
PUBLIC B$LH_SCAN ;[ln]
PUBLIC B$NHINIT ;initialize dynamic space
externNP B$LH_I_ADJ ;[ln] adjust backptrs to any owners in this entry
externNP B$VAR_ALC_GROW ;[ln]
externNP B$ERR_SSC
externNP B$STCPCT
externNP B$STADJ
externNP B$STINIT
externNP B$STSetFree
externNP B$SSClean ; clean string space
ASSERT_NOT_VARHEAP MACRO SEG ;
ENDM ;
PAGE
;***
; LH_ALC_GROW - Grow local heap to support allocation of a block of given size
; Purpose:
; Added with revision [23].
;
; Inputs:
; ES = DS
; BX = total size of local heap space to be allocated
; DL = type of heap entry to allocate.
; CL = if DL=LH_FILE, file number
; CX = if DL anything else, ptr to owner (where backptr should point to)
; Outputs:
; Carry Clear if allocation accomplished successfully
; Modifies:
; SI
; Exceptions:
;
;****
DbPub LH_ALC_GROW
LH_ALC_GROW:
; Step 3 - Get free string entry to heap space, test free entry.
CALL B$LH_FROM_SS ;[ln] get free string from string space
CALL B$LH_ALC_FREE ;test free entry for room
JNC LH_ALC_GROW_DONE; allocated - jump to return to string
; Step 4 - Perform string compaction, get free string, test free entry.
CALL B$STCPCT ;perform the string compaction
CALL B$LH_FROM_SS ;[ln] get free string from string space
CALL B$LH_ALC_FREE ;test free entry for room
JNC LH_ALC_GROW_DONE; allocated - jump to return to string
;
; Step 5 - Kick FH out of DS if possible
;
CALL [b$pFHRaiseBottom] ;[46]
CALL B$LH_FROM_SS ;[ln] get free string from string space
CALL B$LH_ALC_FREE ; test free entry for room
JNC LH_ALC_GROW_DONE;allocated jump to return string
;
; Step 6 - Kick UL data images out of FH and raise the bottom
PUSH AX ;preserve AX-DX across call to
PUSH BX ;B$ULDataRelease, as the far
PUSH CX ;call dispatcher to the quicklibrary
PUSH DX ;can honk on these registers.
CALL B$ULDataRelease ;free UL data images if allocated
POP DX
POP CX
POP BX
POP AX ;recover regs
CALL [b$pFHRaiseBottom] ;give FH's free space to NH
CALL B$LH_FROM_SS ;[ln]get free string from string space
CALL B$LH_ALC_FREE ;test free entry for room
JNC LH_ALC_GROW_DONE;allocated jump to return string
;
; Step 7 - Kick Help out of FH and raise the bottom
PUSH AX ;preserve AX-DX across call to
PUSH BX ;CompressHelp
PUSH CX
PUSH DX
CALL CompressHelp ;Free the help system
POP DX
POP CX
POP BX
POP AX ;recover regs
CALL [b$pFHRaiseBottom] ;give FH's free space to NH
CALL B$LH_FROM_SS ;get free string from string space
CALL B$LH_ALC_FREE ;test free entry for room
Near_Ret: ;Near Return for vector
LH_ALC_GROW_DONE:
RET
;***
; B$LH_FROM_SS - get local heap space from string space
; Purpose:
; Determine if a free entry exists at the end of
; string space. If so, change the string and heap
; space pointers so that it is now part of the local
; heap space.
;
; Mostly rewritten with revision [53].
;
; Strategy (order of attempts swapped with revision [64]):
; (1) If the last entry in the LH is a free entry, tack the free
; string bytes onto that entry and move b$HEAP_END past it.
;
; (2) If the last entry in the LH is NOT a free entry and the free
; string is large enough to create a heap entry (LH_STD_HDR_LEN
; bytes + 2 bytes for back length), then create a new LH entry
; with the free space.
;
; If neither (1) or (2) is possible, then we can't give any of
; the free string to the LH, just exit.
;
; Inputs:
; None.
; Outputs:
; [b$HEAP_FREE] = pointer to new (or enlarged) free heap entry.
; Modifies:
; None.
; Exceptions:
; None.
;****
B$LH_FROM_SS:
ASSERT_NOT_VARHEAP NH_TEXT
PUSH AX ;save registers...
PUSH SI
PUSH DI
CALL B$STSetFree ;SI points to trailing free string
MOV AX,[b$STRING_END] ;get end pointer in AX
SUB AX,SI ;compute size of free string
JZ LH_SS_RETURN ;if no free bytes, exit quickly
; Size of free string (including header) is in AX.
; Pointer to free string header is in SI.
DbAssertTst AX,Z,1,NH_TEXT,<Free string size odd in B$LH_FROM_SS>
; (1) If the last entry in the LH is free, tack the new empty space
; on to it.
MOV DI,[b$HEAP_END] ;[DI] = heap END entry
CMP DI,[B$HEAP_FIRST] ; is END the only entry?
JE LH_SS_TRY_2 ; yes, go create a free entry
ADD DI,[DI+1] ;[DI] = last entry before END
CMP [DI].LHTYPE,LOW LH_FREE ;is entry unallocated?
JNE LH_SS_TRY_2 ;no, go try next option
ADD AX,[DI].LHLEN ;compute new length
JMP SHORT LH_SS_FINISH_UP ; finish updating pointers and exit
; (2) If there are enough free bytes to create a new free entry at the
; end of the LH, do that.
LH_SS_TRY_2:
CMP AX,LH_STD_HDR_LEN+2 ;enough free space?
JB LH_SS_RETURN ;if not, we can't do anything
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -