📄 ssid.asm
字号:
page 49,132
TITLE ssid - Scan support for simple Id opcodes
;***
;ssid.asm - Scan support for simple Id opcodes
;
; Copyright <C> 1986, Microsoft Corporation
;
;Purpose:
;
; This module contains the scanner dispatch routines for simple id opcodes.
; These routines perform all tasks related to moving simple id opcodes from
; one scan state to another.
;
; Scan routines for IdLd opcodes make a stack entry that describes the
; type and location of the id in the scanned pcode. The scan stack
; entry appears as:
;
; push oTx - emitted pcode address of byte following id
; (address at which coercion would be inserted)
; push oTyp - type of expression or ET_RC for records
;
; See scanner.inc for a complete definition of the id stack entry. The
; oTyp word contains constants that uniquely distinguish variable
; references, literals and intermediate expression values.
;
; Routines named Ss_<name> are dispatched by a jmp. These routines
; all return to the scan loop by an indirect jmp through variable scanret.
;
;
;****************************************************************************
.xlist
include version.inc
SSID_ASM = ON
IncludeOnce context
IncludeOnce opid
IncludeOnce pcode
IncludeOnce qbimsgs
IncludeOnce ssint
IncludeOnce txtmgr
IncludeOnce variable
.list
assumes DS, DATA
assumes es, NOTHING
assumes ss, DATA
sBegin SCAN
assumes cs, SCAN
subttl Ss_IdLd
page
;***
;Ss_IdLd Scan Ld variants of simple Id opcodes
;Purpose:
;
; Scan the id variants opIdLd<type>.
;
;Algorithm:
;
; Load opcode data type from the variable table
; Calculate offset for <I|S|F|C> based on oPrsCur and variable table flags
; Load and emit executor
; Copy operand
; Push stack entry
; operand address + 2
; type (with origin bits set)
; Return to main loop
;
;Input:
;
; es:si = pcode emission address
;
;Output:
;
; si updated
;
;Modifies:
;Exceptions:
; Ss_Error
;
;******************************************************************
page
LdRedirect:
mov ax,[bx].VAR_Value ;Value field has new oVar
mov PTRTX[si],ax ;Replace old one
jmp short IdLdRetry
SsProc IdLd,Rude
.erre LOW OPCODE_MASK EQ 0ffh
test byte ptr es:[si-1],HIGH (NOT OPCODE_MASK)
jnz IdLdRetry
mov dx,scanOFFSET mpLdImpOpExe
IdLdRetry:
mov bx,[MrsCur.MRS_bdVar.BD_pb]
add bx,PTRTX[si]
DbChk pVar,bx ;Verify this is a variable
;Check flags to see if we're really doing a load
or WORD PTR [bx].VAR_Flags,FV_STATICSET ; Note that we've seen it
mov ax,[bx].VAR_Flags ; Fetch flags
TestX ax,FVREDIRECT ;Test for redirected variable
jnz LdRedirect ;Go fix the redirected case
xor ax,FVFUN+FVVALUESTORED
TestX ax,FVFUN+FVVALUESTORED ;Test for function call
jz ExecFunc ;This is a function call
call SsIndexType ;DX = Executor address based on oTyp
;CX = oTyp of variable
TestX ax,FVCONST ;Loading a constant?
jnz ConstLoad
or ch,HIGH ST_SimpVar ;Indicate the stack item is a var ref.
ScanTypeSet:
call SsIndexISFC ;Index by ISFC. Restores DS if SizeD
assumes ds,DATA
ScanStack:
;Make stack entry
push di ;oTx for coercion insertion
push cx ;oTyp of variable or ET_RC
jmp [ScanRet]
ConstLoad:
.errnz LOW ST_LitX ; Assure we can use CH
or ch,HIGH ST_LitX ;Constant same as literal w/operand
jmp ScanTypeSet
ExecFunc:
xor cx,cx ;No operands
jmp SsCallFunc
subttl Executor map for IdLd variants
page
;Table mpLdImpOpExe is a list of IdLdImp executors. The list is ordered
;as follows:
; exIdLd<I|S|F|C><type>
;After the Ld executors is Rf excutors for numeric & FS types only.
;
;This table is then followed by IdLdExp executors.
;Type "0" is used by record executors (implicits only).
public mpLdImpOpExe
mpLdImpOpExe label word
mpIdISLd label word
DWEXT exIdISRfTyp
DWEXT exIdISLd2
DWEXT exIdISLd4
DWEXT exIdISLdR4
DWEXT exIdISLdR8
DWEXT exIdISLdSD
DWEXT exIdISLdFS
cbContext = $ - mpIdISLd ;Offset to next frame of executors
mpIdICLd label word
DWEXT exIdICRfTyp
DWEXT exIdICLd2
DWEXT exIdICLd4
DWEXT exIdICLdR4
DWEXT exIdICLdR8
DWEXT exIdICLdSD
DWEXT exIdICLdFS
.erre cbContext EQ ($-mpIdICLd)
mpIdIILd label word
DWEXT exIdIIRfTyp
DWEXT exIdIILd2
DWEXT exIdIILd4
DWEXT exIdIILdR4
DWEXT exIdIILdR8
DWEXT exIdIFLd2
DWEXT exIdIILdFS
.erre cbContext EQ ($-mpIdIILd)
mpIdIFLd label word
DWEXT exIdIFRfTyp
DWEXT exIdIFLd2
DWEXT exIdIFLd4
DWEXT exIdIFLdR4
DWEXT exIdIFLdR8
DWEXT exIdIFLdSD
DWEXT exIdIFLdFS
.erre cbContext EQ ($-mpIdIFLd)
;IdRfImp executor map
public IdLdtoRfMap
IdLdtoRfMap= $-mpLdImpOpExe
mpIdISRf label word
DWEXT exIdISRf
DWEXT exIdISRf
DWEXT exIdISRf
DWEXT exIdISRf
DWEXT exIdISRf
DWEXT exIdISRfFS
.erre cbContext EQ ($-mpIdISRf+2)
mpIdICRf label word
DWEXT exIdICRf
DWEXT exIdICRf
DWEXT exIdICRf
DWEXT exIdICRf
DWEXT exIdICRf
DWEXT exIdICRfFS
.erre cbContext EQ ($-mpIdICRf+2)
; The executors for loading two byte and four byte frame variables are
; also used for referenced to indirect variables. For a load of a frame
; variable, the variable table contains the value which is pushed on the
; stack. For a reference to an indirect variable, the variable table
; contains the address which is then pushed on the stack. Since addresses
; are either two or four bytes, only these entries serve two purposes.
mpIdIIRf label word
DWEXT exIdIIRf
DWEXT exIdIIRf
DWEXT exIdIIRf
DWEXT exIdIIRf
DWEXT exIdIFLd2
DWEXT exIdIIRfFS
.erre cbContext EQ ($-mpIdIIRf+2)
mpIdIFRf label word
DWEXT exIdIFRf
DWEXT exIdIFRf
DWEXT exIdIFRf
DWEXT exIdIFRf
DWEXT exIdIFRf
DWEXT exIdIFRfFS
.erre cbContext EQ ($-mpIdIFRf+2)
;Function call executors
public IdLdtoFuncMap
IdLdtoFuncMap= $-mpLdImpOpExe
DWFILL
DWEXT exFunc0ArgImp
DWEXT exFunc0ArgImp
DWEXT exFunc0ArgImp
DWEXT exFunc0ArgImp
DWEXT exFunc0ArgImp
;Note: The following word is used by MakeRef to
;find the implicit map from the explicit map.
DW mpLdImpOpExe
public mpLdExpOpExe
mpLdExpOpExe label word ;No record type
mpIdESLd label word
DWFILL
DWEXT exIdESLdI2
DWEXT exIdESLdI4
DWEXT exIdESLdR4
DWEXT exIdESLdR8
DWEXT exIdESLdSD
DWEXT exIdESLdFS
.erre cbContext EQ ($-mpIdESLd)
mpIdECLd label word
DWFILL
DWEXT exIdECLdI2
DWEXT exIdECLdI4
DWEXT exIdECLdR4
DWEXT exIdECLdR8
DWEXT exIdECLdSD
DWEXT exIdECLdFS
.erre cbContext EQ ($-mpIdECLd)
mpIdEILd label word
DWFILL
DWEXT exIdEILdI2
DWEXT exIdEILdI4
DWEXT exIdEILdR4
DWEXT exIdEILdR8
DWEXT exIdEIRfSD
DWEXT exIdEILdFS
.erre cbContext EQ ($-mpIdEILd)
mpIdEFLd label word
DWFILL
DWEXT exIdEFLdI2
DWEXT exIdEFLdI4
DWEXT exIdEFLdR4
DWEXT exIdEFLdR8
DWEXT exIdEFRfSD
DWEXT exIdEFLdFS
.erre cbContext EQ ($-mpIdEFLd)
;IdRfExp executor map
.erre IdLdtoRfMap EQ ($-mpLdExpOpExe)
mpIdESRf label word
DWEXT exIdESRfI2
DWEXT exIdESRfI4
DWEXT exIdESRfR4
DWEXT exIdESRfR8
DWEXT exIdESRfSD
DWEXT exIdESRfFS
.erre cbContext EQ ($-mpIdESRf+2)
mpIdECRf label word
DWEXT exIdECRfI2
DWEXT exIdECRfI4
DWEXT exIdECRfR4
DWEXT exIdECRfR8
DWEXT exIdECRfSD
DWEXT exIdECRfFS
.erre cbContext EQ ($-mpIdECRf+2)
mpIdEIRf label word
DWEXT exIdEIRfI2
DWEXT exIdEIRfI4
DWEXT exIdEIRfR4
DWEXT exIdEIRfR8
DWEXT exIdEIRfSD
DWEXT exIdEIRfFS
.erre cbContext EQ ($-mpIdEIRf+2)
mpIdEFRf label word
DWEXT exIdEFRfI2
DWEXT exIdEFRfI4
DWEXT exIdEFRfR4
DWEXT exIdEFRfR8
DWEXT exIdEFRfSD
DWEXT exIdEFRfFS
.erre cbContext EQ ($-mpIdEFRf+2)
;Function call executors
DWFILL
DWEXT exFunc0ArgI2
DWEXT exFunc0ArgI4
DWEXT exFunc0ArgR4
DWEXT exFunc0ArgR8
DWEXT exFunc0ArgSD
subttl Ss_IdSt
page
;***
;Ss_IdStExp, Ss_IdStImp Scan St variants of simple Id opcodes
;Purpose:
;
; Scan the id variants opIdSt<type>.
;
; These routines expect only fundamental BAsiC data types. User types
; are handled by opIdRf variants followed by OpIdOffset opcodes.
;
;Algorithm:
;
; Load exe map address
; Load opcode data type from the variable table
; Compare with type on stack, coerce if different
; Calculate offset for <I|S|F|C> based on oPrsCur and variable table flags
; Load and emit executor
; Copy operand
; Return to main loop
;
;Input:
; es:si = pcode emission address
;Output:
; si updated
;Modifies:
;Exceptions:
; Ss_Error
;******************************************************************
page
StRedirect:
mov ax,[bx].VAR_Value ;Value field has new oVar
mov PTRTX[si],ax ;Replace old one
jmp short IdStRetry
SsProc IdSt,Rude
.erre LOW OPCODE_MASK EQ 0ffh
test byte ptr es:[si-1],HIGH (NOT OPCODE_MASK)
jnz @F
mov dx,scanOFFSET mpStImpOpExe
@@:
test [SsFlags],SSF_ScanAndExec ;Storing a constant?
jnz StoreConst
IdStRetry:
mov bx,[MrsCur.MRS_bdVar.BD_pb]
add bx,PTRTX[si]
DbChk pVar,bx ;Verify this is a variable
;Check flags to see if we're really doing a store
or WORD PTR [bx].VAR_Flags,FV_STATICSET ; Note that we've seen it
mov ax,[bx].VAR_Flags ; Fetch flags
TestX ax,FVREDIRECT ;Test for redirected variable
jnz StRedirect ;Go fix the redirected case
xor ax,FVFUN+FVVALUESTORED
TestX ax,FVFUN+FVVALUESTORED ;Test for function call
jnz IdStore ;Either not function or not static
;Trying to store into function RetVal when not within function defintion
mov ax,ER_DD ;Duplicate definition
call SsError
IdStore:
call SsIndexType ;DX = Executor address based on oTyp
;CX = scan stack oTyp of variable
jcxz NeedOtyp ;Is it a record?
HavOtyp:
call SsIndexISFC ;Index by ISFC
assumes ds,DATA
StoreCoerce:
xchg ax,cx ;AX = oTyp of assignment target
call EnsureArgType ;Check type and possibly insert coercion
test [SsBosFlags],SSBOSF_Const ;In a CONST statement?
jz IdStX
mov al,[SsExecTmp]
mov [SsExecFlag],al ;Restore OPA_fExecute flag
IdStX:
jmp [ScanRet]
NeedOtyp:
mov cx,[bx].VAR_oTyp ;Get real oTyp for coercion
jmp HavOtyp
StoreConst:
mov bl,byte ptr es:[si-1] ; Get HIGH opcode
.erre OPCODE_MASK EQ 3ffh
shr bl,1
shr bl,1 ;Align explicit type
jnz HavConstType ;If explicit, type is in bx
pop bx ;If implicit, get type from stack
push bx ;Restore oTyp on stack
HavConstType:
xor bh,bh
mov mkVar.MKVAR_oTyp,bx
mov ax,PTRTX[si] ;Get oNam
mov mkVar.MKVAR_oNam,ax
or mkVar.MKVAR_flags,FVI_LVAL+FVI_CONST
push dx ;Save executor map
call MakeVariableFar
GETSEGTXTCUR
pop dx
or ax,ax ;Error?
js ConstErr
mov PTRTX[si],ax ;Set oVar
mov bx,si
sub bx,[SsCbTxExpand] ;Compute position in unscanned code
sub bx,[SsScanExStart] ;Relative beginning of this scan
add bx,[SsScanExSrc] ;Position in original text
mov PTRTX[bx],ax ;Set oVar in original source
jmp IdStRetry
ConstErr:
call SsError ;Save MakeVariable error code
MOVSWTX ;Copy oNam field
pop ax
pop bx ;Pop off stack entry
jmp [ScanRet]
;Table mpStImpOpExe is a list of IdStImp executors. The list is ordered
;as follows:
; exIdSt<I|S|F|C><type>
;This table is then followed by IdStExp executors.
;Type "0" entries are used for record executors (implicit types only).
public mpStImpOpExe
mpStImpOpExe label word
mpIdISSt label word
DWEXT exIdISStTyp
DWEXT exIdISSt2
DWEXT exIdISSt4
DWEXT exIdISStR4
DWEXT exIdISStR8
DWEXT exIdISStSD
DWEXT exIdISStFS
.erre cbContext EQ ($-mpIdISSt)
mpIdICSt label word
DWEXT exIdICStTyp
DWEXT exIdICSt2
DWEXT exIdICSt4
DWEXT exIdICStR4
DWEXT exIdICStR8
DWEXT exIdICStSD
DWEXT exIdICStFS
.erre cbContext EQ ($-mpIdICSt)
mpIdIISt label word
DWEXT exIdIIStTyp
DWEXT exIdIISt2
DWEXT exIdIISt4
DWEXT exIdIIStR4
DWEXT exIdIIStR8
DWEXT exIdIIStSD
DWEXT exIdIIStFS
.erre cbContext EQ ($-mpIdIISt)
mpIdIFSt label word
DWEXT exIdIFStTyp
DWEXT exIdIFSt2
DWEXT exIdIFSt4
DWEXT exIdIFStR4
DWEXT exIdIFStR8
DWEXT exIdIFStSD
DWEXT exIdIFStFS
.erre cbContext EQ ($-mpIdIFSt)
public mpStExpOpExe
mpStExpOpExe= $-2 ;No record type
;Note: One word is saved by basing the executor maps at the
;current position minus one. This is acceptable since there
;are no explicit references to records. However, when publics
;are present the static map is no longer first and must have
;a word of filler for record references. This word is defined
;inside the conditional for publics.
mpIdESSt label word
DWEXT exIdESStI2
DWEXT exIdESStI4
DWEXT exIdESStR4
DWEXT exIdESStR8
DWEXT exIdESStSD
DWEXT exIdESStFS
.erre cbContext EQ ($-mpIdESSt+2)
mpIdECSt label word
DWFILL
DWEXT exIdECStI2
DWEXT exIdECStI4
DWEXT exIdECStR4
DWEXT exIdECStR8
DWEXT exIdECStSD
DWEXT exIdECStFS
.erre cbContext EQ ($-mpIdECSt)
mpIdEISt label word
DWFILL
DWEXT exIdEIStI2
DWEXT exIdEIStI4
DWEXT exIdEIStR4
DWEXT exIdEIStR8
DWEXT exIdEIStSD
DWEXT exIdEIStFS
.erre cbContext EQ ($-mpIdEISt)
mpIdEFSt label word
DWFILL
DWEXT exIdEFStI2
DWEXT exIdEFStI4
DWEXT exIdEFStR4
DWEXT exIdEFStR8
DWEXT exIdEFStSD
DWEXT exIdEFStFS
.erre cbContext EQ ($-mpIdEFSt)
subttl SsGetIsfc
;SsGetISFC - return exe map offset for scope
;Input:
; bx = pVar
; dx = index calculated so far
;Output:
; dx = exe map offset updated for scope
;Modifies:
; none
;Preserves:
; none
public SsGetISFC,GetCxISFC
SsGetISFC:
mov cx,cbContext
GetCxISFC:
mov ax,[bx].VAR_Flags ; Fetch flags
TestX ax,FVVALUESTORED ;Test for STATIC
jnz @F ;STATIC variable
add dx,cx ;Move to COMMON executors
TestX ax,FVCOMMON
jnz @F ;COMMON variable (oCommon
;allocated inCOMMON statement)
add dx,cx ;Move to INDIRECT executors
TestX ax,FVFORMAL
jnz @F ;INDIRECT variable
add dx,cx ;Must be a FRAME variable
call SsAllocOFrame ;Frame variables have an oFrame
@@:
ret
sEnd SCAN
end
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -