⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 nammgr.asm

📁 Dos6.0
💻 ASM
📖 第 1 页 / 共 4 页
字号:
	mov	cx,[bx.BD_cbLogical]	;byte count
	DbAssertRel  cx,be,CB_MAX_NAMENTRY,CP,<ONamOfPsd: psd.cb too large>
	push	dx			;put retval back on stack
cEnd	<nogen>				;fall into ONamOfPbCb

;***
;ONamOfPbCb		oNamW = ONamOfPbCb
;Purpose:
;	To return the Name Table offset of a symbol.  If the symbol isn't
;	already in the Name Table, then it is added.  The symbol's case is
;	preserved in tNam , but it is ignored while searching for a match
;	(FoO is the same as fOo). If the cases don't match exactly, then the
;	new symbol will replace the old one in tNam by default; this replacement
;	is suppressed if the Cb input word has it's high bit set. A 0 is 
;	returned in AX to indicate an error condition (out of memory, etc).
;Assumptions:
;	)symbols can never be removed from tNam
;	)Each char in the name part of the symbol can be any valid
;	 ASCII (0-127) except the following:
;	 <Control Char>  < ' >  < { >  < | >  < } >  < ~ >  <DEL>
;	)0 < cb < CB_MAX_NAMENTRY
;Register conventions:
;	DS - pbName segment
;	ES - tNam segment
;	SI - pbName pointer
;	DI - tNam pointer
;Entry:
;	AX = ptr to ASCII string
;	CX = length of ASCII string
;		If the high bit is set and the name is found, the existing
;		name is NOT to be replaced in the table.
;     The following globals are referenced
;	mrsCur.bdlNam => current module's name table
;
;Exit:
;	AX - Name table offset of PbCb input string
;	     0 is returned for error conditions (out of memory).
;	     Special: when fDontCreateName != 0, ax = 0 indicates that the
;	     name wasn't found (and was NOT added to the table).
;	DL = tNam.oNam.flags if AX != 0
;	PSW flags set via an OR AX,AX on exit
;Uses:
;	none
;Exceptions:
;	none
;***************************************************************************
cProc	ONamOfPbCb,<PUBLIC,NEAR,NODATA>,<DI> ;NOTE: matches entry to ONamOfLn
	LocalW	pbName			;ptr to string containing symbol
	LocalW	cbName			;# of bytes in *pbName
	LocalW	pNamCur
	LocalB	fGrowTNam		;set if tNam needs to be grown
					;before exiting
	LocalB	fDontReplaceNam		;FALSE if we should replace name in tbl
	LocalW	lineNum			;line number here, if entry via ONamOfLn
	LocalV	bdlTmp,<SIZE BDL>	
cBegin
	mov	di,tNam 		; not using line # hash table
	mov	bx,0DFDFH-1		;upper case mask for NextChar loop
	mov	dl,31d			;32 hash chains for names (not line #'s)
ONamOf_Common:				;entry from ONamOfLn
	DbChk	tNam
	push	si
	xor	dh,dh
	mov	[fGrowTNam],dh		;assume that tNam doesn't need to grow
	or	ch,ch
	jns	SetReplaceNam		;brif assumption correct

	and	ch,07FH			;reset high bit
	inc	dh			;Don't replace the name in the name
					;  table if entry found, i.e., leave
					;  case of existing name as-is.
SetReplaceNam:
	mov	[fDontReplaceNam],dh
	DbChk	ConStatStructs
	mov	[pbName],ax		;save input
	mov	[cbName],cx		;save input
	xchg	ax,si			;ptr to Name string in SI
	push	bx			; preserve mask
	call	FetchPNam		; bx points to desired mrs
	GETSEG	ES,PTRRS[bx.BDL_seg],,<SIZE,LOAD> ;[10][6][25]
	pop	bx			; restore mask

	DbAssertRel  cx,be,CB_MAX_NAMENTRY,CP,<ONamOfPbCb: cbName too large>
	DbAssertRel  cx,nz,0,CP,<ONamOfPbCb: cbName is 0>
	lodsb				;al = 1st byte of symbol to search for
	dec	cx
	jcxz	Mask_Hash

	dec	cx
	jcxz	Grab_Last		;brif just 2 chars
	
	xor	al,[si]			;hash in second char of name
Grab_Last:				;grab last char for use in hash
	add	si,cx			;point to last char in name
	xor	al,[si]			;use last char in name for hash too
Mask_Hash:
	inc	bx
	jnz	Mask_Hash2		;brif not a numeric - - (must not shift)
					;NOTE: as long as we just use the low
					;	5 bits of this for the hash
					;	index, we don't need to worry
					;	about upper vs. lower case
					;	letters.
	shr	al,1			;Line numbers tend to end in 0; don't
					;  use least significant bit to provide
					;  a more even hash distribution
	dec	bx			
Mask_Hash2:
	;at this point, BX = 0FFFF for Line Number, 0DFDF otherwise
	xor	dh,dh
	and	ax,dx	 		;get the 1st char hash value by doing
					;doing a MOD 32 (or MOD 8 for line #'s).
					;This value is the byte index into
					;tNam which is used to obtain the
					;ptr to the appropriate symbol chain
	shl	ax,1			;convert to word index
	add	di,ax			;DI = offset to 1st char chain ptr,
					;NOTE - this works because tNam
					;is a far heap ( ES:0 => tNam )
	mov	[pNamCur],di		;pass to AddName (if a null chain)
	mov	dx,ES:[di]		;offset of first symbol in chain
					;or 0 if no symbols on chain
NextName:
	mov	cx,[cbName]		;CX=# of bytes in pbName

NextNameCX:				;this label allows the above 'mov cx'
					;to be removed from the inner loop of
					;NextName
	mov	di,dx
	or	di,di			;test ptr to next symbol
	je	AddName 		;brif end of chain encountered

	mov	dx,ES:[di]		;dx=ptr to next symbol in the chain
	mov	[pNamCur],di		;pass to AddName or MapExit
	cmp	ES:NM_SIZE[di],cl	;are both strings the same size?
	jne	NextNameCX		;brif different sizes

	mov	si,[pbName]		;pb of callers name
	add	di,NM_NAME		;DI = ptr to 1st ASCII char of symbol
NextChar:
	lodsb				;AL=next char from pbName
	mov	ah,ES:[di]		;AH=next char from tNam
	inc	di			;bump tNam index
	and	ax,bx			;BX contains 0DFDFH, so this converts
					;AH & AL to upper case by resetting
					;their respective bit 5's. This
					;mapping works because there are
					;no control or special chars in the
					;symbol names.
	cmp	ah,al			;is pbName[SI]=tNam[DI]
	jne	NextName		;brif chars not the same
	loop	NextChar		;loop till mismatch or all chars tested
;
;We found a case insensitive match - if the names are exactly the same, then
;just quit (typical case?), otherwise, tell the UI that it needs to redraw
;the debug screen, and replace the name in the table

	cmp	[fDontReplaceNam],FALSE	;want to replace the name in the table?
	jz	DoReplaceName		;  brif so
MapExit1:				
	jmp	MapExit 		;  nope - just exit

DoReplaceName:
	mov	di,[pNamCur]		;addr of symbol record that matched
	mov	si,[pbName]		;pb of symbol to add
	mov	cx,[cbName]		;# of bytes in pbName
	add	di,NM_NAME		;offset to 1st byte of new entry name
	repz	cmpsb			;are names exactly the same?
	jz	MapExit1		;  brif so - exit

	push	es			;preserve across call
	call	DrawDebugScrFar		;inform UI
	pop	es
	mov	di,[pNamCur]		;addr of symbol record that matched
	jmp	short CopyString	;copy DS:[pbName] to ES:[DI+NM_NAME]
;
; Add pbName to the end of the current chain

AddName:
	xor	ax,ax			;0 for initializing new fields
	mov	[fGrowTNam],TRUE	;tNam needs to grow
;
; make the last entry point to the next empty symbol
;
	mov	di,ES:[cbUsed]		;# of allocated bytes in tNam
					;this is also the addr of the next
					;available byte since cbLogical is
					;greater than cbUsed
	mov	ES:NM_NEXT[di],ax	;NULL ptr for new record
	inc	bx			;is this name for a Line Number?
	jnz	Not_Ln			;  brif not

	mov	al,NM_fLineNum		;set flag to recall that this is a Line#
Not_Ln:
	mov	ES:[di+NM_FLAGS],al	;initialize flags to OFF state
;
; copy the pb string to [ES:DI.name]

CopyString:
	mov	si,[pbName]		;pb of symbol to add
	mov	cx,[cbName]		;# of bytes in pbName
	mov	ES:NM_SIZE[di],cl	;update length field of symbol
					;NOTE - this may be redundant
	add	di,NM_NAME		;offset to 1st byte of new entry name
	rep	movsb			;copy from DS:pbName[SI] to ES:tNam[DI]
	cmp	[fGrowTNam],FALSE	;do we need to grow tNam
	je	MapExit 		;brif symbol wasn't added - don't need
					;to grow tNam
;
; Make sure there will be enough room to add another symbol the next time thru.
; TNam can now be safely grown since the string has been copied and heap
; movement is no longer a problem.
;

	mov	cx,[oRsNam]		;[10]
	jcxz	MrsCur_Okay		; brif want to grow bdl in mrsCur

	; We want to grow the bdlNam for the global mrs, but it's not
	; active. It must be active because (1) cannot safely grow a bdl
	; when it's in a local heap table, and (2) we need to know where
	; the owner of the bdl is in case of heap movement, to refresh es.
	; Therefore, we active and then deactivate the global mrs.
	; NOTE: This assumes that the only reason pMrsNam is non-zero is
	; for global mrs support.
	; Note: we save both oPrsCur AND oMrsCur here instead of oRsCur
	;	    to protect against the special case where a declared/ref'd
	;	    but not defined prs is active here ... in this special case,
	;	    RsActivate of oRsCur would leave the global mrs active ...
	push	[grs.GRS_oPrsCur]	; save for later restore
	push	[grs.GRS_oMrsCur]	; save for later restore
	PUSHI	ax,OMRS_GLOBAL		;[23] oMrs of global mrs
	call	MrsActivateCP		; activate the global mrs

MrsCur_Okay:				
	mov	bx,dataOFFSET mrsCur.MRS_bdlNam	; pointer to tNam bdl
	mov	ax,CB_MAX_NAMENTRY+NM_NAME+NM_NAME 
					; max # of bytes needed to add
					;the next symbol plus the
				 	;overhead needed by the
					;current symbol.
	add	ax,[cbName]		;plus the _NAME field bytes used by
					;the current symbol
	mov	di,[pNamCur]		;addr of last searched name entry

	push	bx			; pass pbdlNam to BdlCheckFree
	push	ax			;pass byte count to BdlCheckFree
	call	BdlCheckFree		;make sure there is enough room in tNam
					;to add another symbol
	xchg	ax,si			; save return code across poss. call
	mov	cx,[oRsNam]		;[10]
	jcxz	MrsCur_Okay1		; brif mrsCur is to be left alone

	; The oRs of the context that was active on input is on the top
	; of the stack. Activate this again, and then refresh pMrsNam in
	; case the mrs table moved and pMrsNam will be used again.
	mov	[oRsNam],0		; reset so global mrs access in
					; MrsActivateCP will be correct
	call	MrsActivateCP		; reactivate input oMrsCur
	call	PrsActivateCP		; reactivate input oMrsCur
	call	Use_GMrs		

MrsCur_Okay1:				
	sub	ax,ax			; in case of error
	or	si,si			; BdlCheckFree return code
	je	ONamOfPbCb_Exit		;brif not enough memory - the current
					;name isn't added to tNam - even
					;though the _NAME field has been
					;updated.
	mov	si,[cbName]		;# of bytes in new symbol
	add	si,NM_NAME		;compensate for header bytes
					;SI = # of bytes in new entry
	call	FetchPNam		; bx points to desired mrs
	mov	dx,PTRRS[bx.BDL_cbLogical] ;[10] # of bytes in Name Table
	add	dx,si			   ; + padding for next symbol
	js	ONamOfPbCb_Exit		;brif table has grown > 32k
					;  see module header for reason(s) for
					;  this restriction
	mov	PTRRS[bx.BDL_cbLogical],dx  ;[10]
	
	GETSEG	ES,PTRRS[bx.BDL_seg],,<SIZE,LOAD> ;[14][10][6]
					 ;	  may have been changed by the
					 ;	  call to BdlCheckFree

					;make the last entry point to the 
					; next empty symbol
	mov	ax,ES:cbUsed		;# of tNam bytes already used
					;this is also the addr of the next
					;available byte since cbLogical is
					;greater than cbUsed
	mov	ES:[di],ax		;make the last entry point to new entry
	mov	di,ax			;return new oNam to caller
	add	ax,si			;cbUsed + size of new entry
	mov	ES:cbUsed,ax		;# of bytes used by the Name Table
	mov	[pNamCur],di		;return new oNam to caller
MapExit:
	mov	bx,[pNamCur]		;return name offset to caller in AX
	mov	dl,ES:NM_FLAGS[bx] 	;get the flag byte
	xchg	ax,bx
ONamOfPbCb_Exit:
	pop	si
	or	ax,ax			;set flags for callers
cEnd



;***
;TNamInit		TNamInit()
;Purpose:
;	To initialize the Name Table structure and any other data used by
;	the Name Table Manager.  A zero is returned in AX if there was not
;	enough memory.
;Entry:
;	sbToUse - 0 means use any sb for this table. If non-zero, then this
;			sb value is to be used.
;	mrsCur.bdlNam = current module's name table
;Exit:
;	AX = 0 if not enough memory was available
;Uses:
;	none
;Exceptions:
;	none
;***************************************************************************
cProc	TNamInit,<PUBLIC,NEAR,NODATA>,<DI>
	parmW	sbToUse 		
cBegin
	mov	ax,dataOFFSET mrsCur.MRS_bdlNam  ; ptr to tNam bdl
	push	ax			; parm to BdlAlloc
	cCall	BdlFree,<ax>		; in case name table is an owner
	mov	ax,NM_INIT_TABLE_SZ	;# of bytes to allocate
	push	ax			;pass low word of cb to BdlAlloc
	PUSHBDL_TYPE  pgtypEBNameTable,ax ; pass sb type for EB version
	mov	cx,[sbToUse]		
	jcxz	Use_Any_Sb

	push	cx			
	call	BdlAllocSb		
	jmp	short TNamInit_Cont	
Use_Any_Sb:				
	call	BdlAlloc		;allocate a large far heap for NamTab
TNamInit_Cont:
	or	ax,ax			;check return code
	je	TNIExit 		;brif heap wasn't allocated
;
;we now own a far heap entry - initialize it
;
	GETSEG	ES,[mrsCur.MRS_bdlNam_seg],,<SIZE,LOAD> ;[6]

	mov	cx,mrsCur.MRS_bdlNam_cPhysical ;# of paragraphs in Name Table
	shl	cx,1			;convert cPara to cBytes
	shl	cx,1			;  (under DOS 5 this already is cBytes)
	shl	cx,1
	shl	cx,1
	mov	di,tNam 		;di=base addr of tNam
					;NOTE - tNam is a far heap
	sub	cx,di			; zero-fill all but initial bytes
	sub	ax,ax			;AX=0
	REP	STOSB			;Initialize the Name table
	mov	ax,oNamFirst		;offset to 1st usable entry
	mov	ES:cbUsed,ax		;# of bytes currently being used
					;by tNam
	add	ax,NM_NAME+CB_MAX_NAMENTRY 
					; # of bytes currently being used
					;by tNam + enough padding to add
					;another symbol
	mov	mrsCur.MRS_bdlNam_cbLogical,ax ;total size of tNam
TNIExit:
cEnd

;***
;CopyONamPb		cbW = CopyONamPb
;Purpose:
;	To copy the ASCII chars in a name table entry to the callers buffer.
;	The # of ASCII characters copied is returned.
;Assumptions:
;	pbW contains room for at least CB_MAX_NAMENTRY chars
;Register conventions:
;	DS - tNam segment
;	ES - pb segment
;	SI - tNam pointer
;	DI - pb pointer

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -