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

📄 prscg.asm

📁 [随书类]Dos6.0源代码
💻 ASM
📖 第 1 页 / 共 3 页
字号:
	cmp	[pdcl.PDCL_cParms],ax
	jne	MarkDisp		;brif got a parm list
	dec	[pdcl.PDCL_cParms]	;set to UNDEFINED so scanner knows
					; to not use this for parm
					; type/count checking
	jmp	SHORT MarkDisp

NotDeclare:
	;If we don't get MARK(4), this SUB/FUNCTION has no STATIC keyword
	and	[prsCur.PRS_flags],NOT FP_STATIC

;-------------------------------------------------
;walk through MARK(xxx) entries from left to right
;-------------------------------------------------
MarkDisp:
	mov	si,MAX_STK_MARK
DeclMarkLoop:
	cmp	[pCurStkMark],si
	jne	DeclNextMark
	jmp	SHORT DeclEndOfMarks

DeclNextMark:
	dec	si
	dec	si
	mov	di,[si]			;di = oDstOpcode
	dec	si
	dec	si
	mov	ax,[si]			;ax = al = markId
	dec	ax
	DbAssertRel ax,be,9,CP,<Unexpected MARK in CgDeclare()>
	shl	ax,1
	xchg	ax,bx			;bx = 2 * (markId - 1)
	jmp	WORD PTR cs:DeclDispTbl[bx]	;dispatch based on markId

DeclDispTbl:
	DW	DeclMark1		;CDECL
	DW	DeclMark2		;ALIAS
	DW	DeclMark3		;parms (before left paren)
	DW	DeclMark4		;STATIC
	DW	DeclMark5		;single line DEF
	DW	DeclMark6		;1st parm (after left paren)

;MARK(1):  Got CDECL directive
DeclMark1:
	call	ErrIfPrsHasTxtTbl
	jne	DeclMarkLoop		;brif prs has a text table
	.errnz	DCLA_cdecl - 8000h
	or	[procAtr_HI],80h	;remember we got CDECL
	jmp	SHORT DeclMarkLoop

;MARK(2):  Got ALIAS directive
DeclMark2:
	call	ErrIfPrsHasTxtTbl
	mov	[oDstAlias],di		;save offset to opLitSD("<alias>")
	jmp	SHORT DeclMarkLoop

;MARK(3):  got offset to formal parm list
DeclMark3:
	mov	[oDstParms],di
	jmp	SHORT DeclMarkLoop

;MARK(4):  got STATIC keyword at end of proc definition
DeclMark4:
	or	[prsCur.PRS_flags],FP_STATIC
	jmp	SHORT DeclMarkLoop

;MARK(5):  got single line DEF FN
DeclMark5:
	mov	[oDstEndDef],di
	mov	ax,opEndSingleDef
	call	Emit16_AX
	mov	ax,2
	call	Emit16_AX		;emit cntEos word
	call	Emit16_0		;emit space for link field
	jmp	SHORT DeclMarkLoop

;MARK(6):  got ( [parmlist] )
DeclMark6:
	cmp	[pdcl.PDCL_cParms],UNDEFINED ;so scanner knows to not use this
					; for parm type/count checking
	jne	DeclMarkLoop		;brif got a parm list
	inc	[pdcl.PDCL_cParms]	;so scanner knows to use this declare
					; for parm type/count checking
	jmp	SHORT DeclMarkLoop


DeclEndOfMarks:
	;Copy Alias text after formal parms
	mov	ax,[oDstAlias]
	or	ax,ax
	je	NoAliasArg
	call	CopyLit			;ax = cbAlias
	mov	[cbLibInfo],ax
	shl	al,1
	shl	al,1
	.errnz	DCLA_cbAlias - 7C00h
	or	[procAtr_HI],al		;save cbAlias in pcode field


	;squeeze source of ALIAS lit out of pcode buffer
	;BdShiftLeft((bd *)&ps.bdpDst, oDstAlias, oDstParms - oDstAlias)
	
	PUSHI	ax,<dataOFFSET ps.PS_bdpDst>
	push	[oDstAlias]
	mov	ax,[oDstParms]
	sub	ax,[oDstAlias]		;ax = number of bytes to delete
	push	ax
	sub	[oDstParms],ax		;update for the left shift
	sub	[oDstEndDef],ax		;update for the left shift
	call	BdShiftLeft		;grow buf, can cause heap movement

NoAliasArg:
	;Now make room for things to insert before parm list:
	; opcode, byte-count-till-end-of-stmt, link field for DEF FNs, oPrs
	mov	si,10			;assume we need to insert 10 bytes
	cmp	[pdcl.PDCL_procType],PT_DEFFN
	jne	NotDefFn1		;brif not DEF FN stmt
	inc	si			;need 2 extra bytes for link field
	inc	si
NotDefFn1:
	;BdShiftRight((bd *)&ps.bdpDst, oDstParms, cbInsert)
	PUSHI	ax,<dataOFFSET ps.PS_bdpDst>
	push	[oDstParms]
	push	si			;pass cbInsert parm
	call	BdShiftRight
	or	ax,ax
	jne	ShiftOk			;brif no out-of-memory error
	call	ParseErrOm		;Error "Out of memory"
	jmp	SHORT DeclExit

ShiftOk:
	call	SetDstPbCur		;update ps.bdpDst.pbCur after BdShift...
	push	ds
	pop	es			;es = ds for stosw below
	mov	di,[oDstParms]
	add	di,[ps.PS_bdpDst.BDP_pb]
	mov	ax,[opcode]
	stosw				;store opcode in pcode buffer

	;emit cntEos operand
	mov	ax,[oDstEndDef]
	sub	ax,[oDstParms]
	add	ax,si			;include cbInsert
	add	ax,[cbLibInfo]		;add #bytes in LIB and ALIAS clause
	sub	ax,4
	inc	ax			;round up to even byte count
	and	al,0FEH
	stosw				;store cntEos operand

	cmp	[pdcl.PDCL_procType],PT_DEFFN
	jne	NotDefFn2		;brif not DEF FN stmt
	stosw				;leave room for DEF FN link field
NotDefFn2:
	mov	ax,[pdcl.PDCL_oPrs]
	or	ax,ax
	jns	NotUnboundDefFn
	mov	ax,[pdcl.PDCL_oNam]	;for [DECLARE] DEF FNs, in SS_RUDE
					;state, emit the oNam
NotUnboundDefFn:

	stosw				;store oPrs/oNam operand
	mov	ax,[procAtr]
	stosw				;store proc's oTyp
	mov	ax,[pdcl.PDCL_cParms]
	stosw				;store cParms operand
DeclExit:
cEnd

;*********************************************************************
; CopyLit(ax:oDstLit)
; Purpose:
;	Move the ASCII text of an opLitSD to the end of the pcode buffer.
;	If string is longer than 255 bytes, it is truncated.
; Entry:
;	ax = offset into pcode buffer to opLitSD opcode
;	[EB] bx = TRUE iff length of string is to output as byte preceeding
;		  text of string. 
; Exit:
;	string is moved to end of pcode buffer and the opLitSd is removed
;	ax = length of string
;
;*********************************************************************
CopyLit	PROC NEAR
	push	si
	mov	si,ax
	add	si,[ps.PS_bdpDst.BDP_pb]
	lodsw				;skip opLitSD opcode
	DbAssertRel ax,e,opLitSD,CP,<CopyLit: expected opLitSD> 
	lodsw				;ax = cb operand from opLitSD
	or	ah,ah
	je	LenOk
	mov	ax,255			;truncate string
LenOk:
	push	ax			;save for return value
	inc	ax			;round up to word count
	shr	ax,1
	mov	cx,ax
	jcxz	CLitExit		;brif entire string has been copied
CLitLoop:
	push	cx			;save word count
	lodsw				;ax = next 2 bytes of string

	sub	si,[ps.PS_bdpDst.BDP_pb] ;Emit16 can cause heap movement
	call	Emit16_AX
	add	si,[ps.PS_bdpDst.BDP_pb] ;reconvert offset to pointer

	pop	cx			;restore word count
	loop	CLitLoop
CLitExit:
	pop	ax			;ax = string length
	pop	si
	ret
CopyLit	ENDP

;*********************************************************************
; CgCall(opcode)
; Purpose:
;	Called to generate pcode for the following bnf:
;	 tkCALL (MARK(1) IdImplicit
;	   [tkLParen IdCallArg {tkComma IdCallArg} tkRParen])
;	 tkCALLS MARK(1) IdImplicit
;	   [tkLParen IdCallArg {tkComma IdCallArg} tkRParen]
;
;*********************************************************************
PUBLIC	CgCall
CgCall	PROC NEAR
	push	si			;save caller's si
	mov	bx,MAX_STK_MARK
	mov	si,[bx-2]		;si=offset in pcode for item after MARK
	push	ax			;save opcode for Emit16 below
	mov	bx,[ps.PS_bdpDst.BDP_pb]
	mov	ax,[bx][si]		;ax = oNamIdSub
	call	SubRef			;ax = oPrs for sub being called
					;We can ignore error results, because
					;if error occurs, no code will ever
					;try to activate this oPrs, because
					;line will be stored as opReParse

	;delete the information emitted by NtIdImplicit()
	;BdShiftLeft((bd *)&ps.bdpDst, oDstCur, 2)
	
	PUSHI	dx,<dataOFFSET ps.PS_bdpDst>
	push	si
	PUSHI	dx,2
	mov	si,ax			;si = oPrs
	call	BdShiftLeft		;grow buf, can cause heap movement
	call	SetDstPbCur		;set ps.bdpDst.pbCur after BdShiftLeft
	call	Emit16			;emit opcode pushed ~15 lines above
	push	[cIdArgs]
	call	Emit16			;emit arg count
	push	si			;push oPrs
	call	Emit16
	pop	si			;restore caller's si
	ret
CgCall	ENDP

;*********************************************************************
; VOID NEAR CgRun(opcode)
; Purpose:
;	Invoked to generate code for the following bnf:
;	 tkRUN [(Ln MARK(1)) | (Exp MARK(2))]; <CgRun()>
;
;*********************************************************************
PUBLIC	CgRun
CgRun	PROC NEAR
	mov	bx,[pCurStkMark]
	cmp	bx,MAX_STK_MARK
	mov	ax,opStRunMain		;ax = opcode to emit for RUN
	je	RunEmitExit		;brif simple RUN (no MARKs)
	DbAssertRelB [bx],be,2,CP,<Invalid MARK id in CgRun()>
	cmp	BYTE PTR [bx],1
	jne	RunFile			;brif markId != 1  (RUN <filename>)

	;Got RUN <line number>, insert opStRunLabel before Ln
	mov	bx,[bx+2]		;bx = pcode offset
	dec	bx
	dec	bx			;bx = pcode offset where opcode is to go
	mov	ax,opStRunLabel
	call	InsertOp		;insert word AX at offset BX
	jmp	SHORT RunExit

RunFile:
	mov	ax,opStRunFile
RunEmitExit:
	call	Emit16_AX
RunExit:
	ret
CgRun	ENDP

;*********************************************************************
; VOID NEAR CgInput(opcode)
; Purpose:
;	Invoked to generate code for the following bnf:
;
;	tkINPUT 
;	 [(lbsInpExpComma MARK(16)) |
;	  (tkSColon MARK(2) [LitString MARK(4) (tkSColon | (tkComma MARK(1)))])|
;	  (LitString MARK(4) (tkSColon | (tkComma MARK(1))))]
;	 MARK(8) IdAryElemRef EMIT(opStInput) {tkComma IdAryElemRef
;                                              EMIT(opStInput)}
;	 EMIT(opInputEos)
;	   <CgInput(opInputPrompt)>
;
;	tkLINE tkINPUT
;	 [(lbsInpExpComma MARK(16)) |
;	  (tkSColon MARK(2) [LitString MARK(4) (tkSColon | (tkComma MARK(1)))]) |
;	  (LitString MARK(4) (tkSColon | (tkComma MARK(1))))]
;	 IdAryElemRef
;	   <CgInput(opStLineInput)>
;
;	It maps syntax to pcode as follows:
;	   INPUT [;] [prompt (,|;) <list> =>
;	    [sdExp] opInputPrompt(cnt,mask,<typelist>)
;	If prompt is followed by a semicolon, FINP_QSupress is not ORed into
;          'mask' which causes a question mark to be appended to the prompt
;          string.
;	The optional semicolon after INPUT causes FINP_CrLf not to be ORed into
;	   'mask' which causes the user's terminating carriage return not to be
;	   echoed.
;
;*********************************************************************
PUBLIC	CgInput
CgInput	PROC NEAR
.errnz	FINP_QSupress - 1
.errnz	FINP_CrLf - 2
.errnz	FINP_Prompt - 4
	push	si			;save caller's si
	push	di			;save caller's di
	sub	di,di			;init bit mask
	mov	bx,MAX_STK_MARK

;OR bit mask with to 1 for comma after prompt (MARK(1)),
;		     2 for semicolon after INPUT (MARK(2)),
;		     4 for prompt (MARK(4))
InpMarkLoop:
	cmp	[pCurStkMark],bx
	je	InpMarkLoopDone
	dec	bx
	dec	bx
	mov	si,[bx]			;si = oDstOpcode from mark stack
	dec	bx
	dec	bx
	cmp	WORD PTR [bx],16
	jne	NotMark16		;brif markId != 16
	cmp	ax,opStLineInput
	je	InpMarkLoop		;brif not INPUT #n
	jmp	SHORT InpExit		;If INPUT #n, pcode is already complete

NotMark16:
	or	di,[bx]
	DbAssertRel di,b,16,CP,<Invalid markId in CgInput>
	jmp	SHORT InpMarkLoop

;di = bit mask (built by ORing markIds)
;ax = opcode
;
InpMarkLoopDone:
	cmp	ax,opStLineInput
	jne	NotLineInput
	call	Emit16_AX		;emit opcode
	push	di			;emit bit mask
	call	Emit16
	jmp	SHORT InpExit

⌨️ 快捷键说明

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