mirror of https://github.com/tongzx/nt5src
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1238 lines
20 KiB
1238 lines
20 KiB
title asmhelp - assembler helpers
|
|
page ,132
|
|
|
|
;--------------------------------------------------------------------
|
|
;
|
|
; asmhelp fast assembly language helpers for masm
|
|
;
|
|
; (C)Copyright 1985 Microsoft Corp.
|
|
;
|
|
; Revision history
|
|
;
|
|
; 04/02/85 Greg Whitten
|
|
; initial version
|
|
; scanatom speedups
|
|
;
|
|
;--------------------------------------------------------------------
|
|
|
|
ifndef MSDOS
|
|
ifndef CPDOS
|
|
.286
|
|
endif
|
|
endif
|
|
.model medium,c
|
|
|
|
if1
|
|
|
|
alignCode macro
|
|
align 4
|
|
endm
|
|
|
|
.xlist
|
|
include mixed.inc
|
|
.list
|
|
.lall
|
|
|
|
endif
|
|
|
|
cLang = 1
|
|
CASEL = 1
|
|
SYMMAX = 31
|
|
TSYMSIZE = 451 ; from asmsym.c
|
|
|
|
LEGAL1ST = 08h ; legal 1st token character mask
|
|
TOKLEGAL = 10h ; legal token character mask
|
|
|
|
.code A_TEXT
|
|
|
|
extrn Pascal ERRORC:near
|
|
extrn Pascal CREFNEW:far
|
|
extrn Pascal CREFOUT:far
|
|
extrn Pascal OFFSETASCII:far
|
|
extrn Pascal listline:far
|
|
extrn Pascal crefline:far
|
|
extrn Pascal tryOneFile:far
|
|
|
|
extrn _ffree:far
|
|
|
|
ifndef MSDOS
|
|
extrn read:proc
|
|
extrn write:proc
|
|
extrn lseek:proc
|
|
extrn free:proc
|
|
endif
|
|
|
|
ifdef CPDOS
|
|
extrn Pascal DosRead:far
|
|
extrn Pascal DosChgFilePtr:far
|
|
extrn Pascal DosWrite:far
|
|
endif
|
|
.data
|
|
|
|
extrn _asmctype_:byte
|
|
extrn _asmcupper_:byte
|
|
extrn _asmTokenMap_:byte
|
|
extrn caseflag:byte
|
|
extrn fCrefline:byte
|
|
extrn fNeedList:byte
|
|
extrn objing:byte
|
|
extrn srceof:byte
|
|
extrn crefing:byte
|
|
extrn emitrecordtype:byte
|
|
|
|
extrn linebp:word
|
|
extrn linelength:byte
|
|
extrn linebuffer:byte
|
|
extrn linessrc:word
|
|
extrn listconsole:byte
|
|
extrn begatom:word
|
|
extrn endatom:word
|
|
extrn errorlineno:word
|
|
extrn errorcode:word
|
|
extrn oOMFCur:dword
|
|
extrn handler:byte
|
|
extrn lbufp:word
|
|
extrn pass2:byte
|
|
extrn save:byte
|
|
extrn svname:word
|
|
extrn obj:word
|
|
extrn pFCBCur:word
|
|
extrn naim:word
|
|
extrn objerr:word
|
|
extrn objectascii:word
|
|
extrn iProcCur:word
|
|
|
|
extrn symptr:dword
|
|
extrn lsting:byte
|
|
extrn lbuf:byte
|
|
|
|
ifdef BCBOPT
|
|
extrn hash:word
|
|
extrn lcname:word
|
|
extrn svhash:word
|
|
extrn svlcname:word
|
|
extrn fNoCompact:byte
|
|
endif
|
|
|
|
|
|
@CurSeg ends
|
|
|
|
assume ds:nothing
|
|
extrn tsym:dword
|
|
assume ds:@data
|
|
|
|
.data?
|
|
|
|
mapstr db 10 dup(?) ; use this if /Ml
|
|
|
|
ifdef M8086OPT
|
|
qlcname db SYMMAX+1 dup(?)
|
|
|
|
dw 1 dup(?) ;hash for name
|
|
db 1 dup(?) ;cb for name
|
|
qname db SYMMAX+1 dup(?)
|
|
|
|
qsvlcname db SYMMAX+1 dup(?)
|
|
|
|
dw 1 dup(?) ;hash for name
|
|
db 1 dup(?) ;cb for name
|
|
qsvname db SYMMAX+1 dup(?)
|
|
|
|
endif
|
|
|
|
ifdef M8086OPT
|
|
public qlcname, qname, qsvlcname, qsvname
|
|
endif
|
|
|
|
.data
|
|
fEatBlanks db 1 ; flag for common getatom & getatomend
|
|
cbLeft dw 0 ; count of bytes left in lbuf
|
|
rarea dw 0 ; area for DosRead/Write to tell how much it read
|
|
|
|
.code A_TEXT
|
|
|
|
ifdef M8086OPT
|
|
|
|
;*** getatom () ( hash = scanatom() )
|
|
|
|
nulToken:
|
|
mov lbufp,si ; update buffer pointer
|
|
mov [di+SYMMAX+4],bh
|
|
pop di
|
|
pop si
|
|
retn
|
|
|
|
getatomComm:
|
|
|
|
hProc <getatom near>, <uses si di>
|
|
|
|
mov ax,ds
|
|
mov es,ax
|
|
mov di,lbufp
|
|
mov ax,0920H ; load tab|space into AX
|
|
or cx,0FFFFH ; large count to CX
|
|
alignCode
|
|
skipbeg:
|
|
repe scasb ; look for space
|
|
xchg al,ah
|
|
dec di
|
|
repe scasb ; then tab
|
|
dec di
|
|
cmp byte ptr [di],ah
|
|
je skipbeg ; repeat if still space
|
|
|
|
xor ax,ax
|
|
xor bx,bx
|
|
mov si,di
|
|
mov di,lcname
|
|
|
|
mov bl,[si]
|
|
test byte ptr _asmctype_[bx],LEGAL1ST
|
|
jz nulToken
|
|
|
|
xor dx,dx ; initial hash value
|
|
mov cx,SYMMAX
|
|
mov begatom,si ; start of atom
|
|
|
|
cmp bl,'.' ;special case for token starting
|
|
jne notDot ;with .
|
|
inc si
|
|
dec cx
|
|
mov al,bl
|
|
mov dx,ax
|
|
stosb
|
|
mov [di+SYMMAX+3],al
|
|
notDot:
|
|
mov bx,offset _asmTokenMap_ ; character translation table
|
|
|
|
cmp caseflag,CASEL
|
|
je short tokloop ; Mu or Mx - use MAP version
|
|
|
|
|
|
alignCode
|
|
Mtokloop:
|
|
rept 3
|
|
lodsb ; al = get next character
|
|
stosb ; *lcname++ = cc
|
|
xlat
|
|
|
|
mov [di+SYMMAX+3],al ; *naim++ = cc
|
|
add dx,ax ; swapped hash += MAP(cc)
|
|
|
|
dec cx
|
|
or al,al
|
|
jz short tokdone
|
|
jcxz skiptok
|
|
endm
|
|
|
|
lodsb
|
|
stosb
|
|
xlat
|
|
|
|
mov [di+SYMMAX+3],al
|
|
add dx,ax
|
|
|
|
or al,al
|
|
loopnz Mtokloop
|
|
|
|
jz tokdone
|
|
jmp skiptok
|
|
|
|
tokloop:
|
|
rept 3
|
|
lodsb ; al = get next character
|
|
stosb ; *lcname++ = cc
|
|
|
|
mov [di+SYMMAX+3],al ; *naim++ = cc
|
|
xlat
|
|
add dx,ax ; swapped hash += MAP(cc)
|
|
|
|
dec cx
|
|
or al,al
|
|
jz short tokdone0
|
|
jcxz skiptok
|
|
endm
|
|
|
|
lodsb
|
|
stosb
|
|
|
|
mov [di+SYMMAX+3],al
|
|
xlat
|
|
add dx,ax
|
|
|
|
or al,al
|
|
loopnz tokloop
|
|
|
|
jz tokdone0
|
|
jmp short skiptok
|
|
|
|
tokdone0:
|
|
mov [di+SYMMAX+3],al ; terminate
|
|
tokdone:
|
|
mov [di-1],al
|
|
dec si
|
|
mov endatom,si
|
|
jmp short skipend
|
|
|
|
skiptok:
|
|
dec cx
|
|
|
|
skipnext:
|
|
lodsb ; eat extra characters in token
|
|
xlat
|
|
or al,al
|
|
jnz skipnext ; skip token
|
|
|
|
mov endatom,si
|
|
|
|
mov [di],al
|
|
inc di
|
|
mov [di+SYMMAX+3],al ; terminate
|
|
dec si
|
|
|
|
skipend: ; skip for getatom only
|
|
mov bx,cx
|
|
mov di,si
|
|
cmp fEatBlanks,0
|
|
jz noEatSemie
|
|
|
|
mov ax,0920H ; load tab|space into AX
|
|
or cx,0FFFFH ; large count to CX
|
|
alignCode
|
|
skipend1:
|
|
repe scasb ; look for space
|
|
xchg al,ah
|
|
dec di
|
|
repe scasb ; then tab
|
|
dec di
|
|
cmp byte ptr [di],ah
|
|
je skipend1 ; repeat if still space
|
|
|
|
skipend2: ; skip trailing white space
|
|
mov lbufp,di ; update buffer pointer
|
|
|
|
xor ax,ax
|
|
mov al,SYMMAX-1 ; compute token length
|
|
sub al,bl
|
|
|
|
mov bx,naim
|
|
mov byte ptr [bx-1],al ; save prefixed cb
|
|
mov word ptr [bx-3],dx ; save prefixed hash
|
|
|
|
hRet
|
|
|
|
noEatSemie:
|
|
mov fEatBlanks,1
|
|
jmp skipend2
|
|
|
|
hEndp
|
|
|
|
;*** getatomend () ; get an token without skiping trailing spaces
|
|
|
|
hProc <getatomend near>
|
|
|
|
mov fEatBlanks,0
|
|
jmp getatomComm
|
|
|
|
hEndp
|
|
|
|
endif ;M8086OPT
|
|
|
|
ifdef M8086OPT
|
|
;*** inset (value, setptr)
|
|
|
|
hProc <inset near>, <uses si di>, value:byte, setptr:word
|
|
|
|
mov ax,ds
|
|
mov es,ax
|
|
cld
|
|
mov al,value
|
|
mov di,setptr
|
|
mov cl,[di]
|
|
inc di
|
|
xor ch,ch ; cx = set length
|
|
repne scasb ; scan for al in es:di
|
|
je insetT ; yes - return TRUE
|
|
xor ax,ax ; return FALSE
|
|
insetexit:
|
|
hRet
|
|
|
|
insetT: mov ax,1 ; return TRUE
|
|
jmp short insetexit
|
|
|
|
hEndp
|
|
|
|
endif ;M8086OPT
|
|
|
|
|
|
|
|
;*** strffcmp (far1, far2)
|
|
|
|
hProc <strffcmp far>, <uses si di>, far1:dword, far2:dword
|
|
|
|
cld
|
|
les di,far2
|
|
lds si,far1
|
|
mov bx,di ; save start of string
|
|
cmpsb ; fast 1st char check
|
|
jnz ffne
|
|
dec si
|
|
xor ax,ax ; search for 0 terminator
|
|
mov cx,-1
|
|
repne scasb
|
|
neg cx ; cx = byte count for compare
|
|
mov di,bx
|
|
repz cmpsb
|
|
ffne: mov al,[si-1]
|
|
sub al,es:[di-1] ; ax = 0 if equal
|
|
cbw
|
|
|
|
push ss
|
|
pop ds
|
|
hRet
|
|
|
|
hEndp
|
|
|
|
|
|
;*** strnfcmp (near1, far2)
|
|
|
|
hProc <strnfcmp near>, <uses di si>, near1:word, far2:dword
|
|
|
|
cld
|
|
mov si,near1
|
|
les di,far2
|
|
mov bx,di ; save start of string
|
|
cmpsb ; fast check on 1st character
|
|
jnz nfne
|
|
dec si
|
|
xor ax,ax ; search for 0 terminator
|
|
mov cx,-1
|
|
repne scasb
|
|
neg cx ; cx = byte count for compare
|
|
mov di,bx
|
|
repz cmpsb
|
|
nfne: mov al,[si-1]
|
|
sub al,es:[di-1] ; ax = 0 if equal
|
|
|
|
hRet
|
|
|
|
hEndp
|
|
|
|
ifdef M8086OPT
|
|
|
|
;*** switchname ()
|
|
|
|
hProc <switchname near>
|
|
alignCode
|
|
|
|
mov ax,naim ;; (naim) <--> (svname)
|
|
xchg ax,svname
|
|
mov naim,ax
|
|
mov ax,lcname ;; (lcname) <--> (svlcname)
|
|
xchg ax,svlcname
|
|
mov lcname,ax
|
|
hRet
|
|
|
|
hEndP
|
|
|
|
endif ;M8086OPT
|
|
|
|
|
|
|
|
ifdef M8086OPT
|
|
|
|
;*** I/O routines: readmore, getline, ebuffer, etc.
|
|
|
|
objfile struc
|
|
ofh dw ?
|
|
ifdef MSDOS
|
|
pos dd ?
|
|
buf dd ?
|
|
else
|
|
pos dw ?
|
|
buf dw ?
|
|
endif ;MSDOS
|
|
cnt dw ?
|
|
siz dw ?
|
|
oname dw ?
|
|
objfile ends
|
|
|
|
endif ;M8086OPT
|
|
|
|
|
|
|
|
ifdef M8086OPT
|
|
|
|
;*** ebuffer - write out object buffer
|
|
;
|
|
; ebuffer (rectype, bufpos, buffer)
|
|
|
|
ebyte macro
|
|
dec [bx].cnt
|
|
jge short $+5
|
|
call edump ; dump buffer
|
|
stosb
|
|
add ah,al
|
|
endm
|
|
|
|
hProc <ebuffer near>, <uses si di>, rectype:byte, bufpos:word, buffer:word
|
|
|
|
mov si,buffer
|
|
mov cx,bufpos
|
|
sub cx,si ; cx = buffer count
|
|
jz ebufdone
|
|
cmp objing,0
|
|
je ebufdone ; return if no object file
|
|
|
|
mov ax,cx
|
|
add ax,4
|
|
add word ptr oOMFCur,ax ; oOMFCur += cbBuffer + 3
|
|
adc word ptr oOMFCur.2,0
|
|
ifndef MSDOS
|
|
mov ax,ds
|
|
mov es,ax
|
|
endif
|
|
cld
|
|
xor ax,ax ; ah = 0 (initial checksum)
|
|
mov al,rectype
|
|
mov bx,OFFSET obj ; bx = obj file data structure pointer
|
|
ifdef MSDOS
|
|
les di,[bx].pos ; es:di = output buffer position
|
|
else
|
|
mov di,[bx].pos ; di = output buffer position
|
|
endif
|
|
ebyte ; output record type
|
|
inc cx ; + 1 for record length
|
|
mov al,cl
|
|
ebyte
|
|
mov al,ch
|
|
ebyte ; output record length
|
|
dec cx ; - 1 for buffer loop
|
|
alignCode
|
|
ebufloop: ; output buffer
|
|
lodsb
|
|
ebyte
|
|
loop ebufloop
|
|
mov al,ah ; output checksum
|
|
neg al
|
|
ebyte
|
|
ifdef MSDOS
|
|
mov word ptr [bx].pos,di ; reset buffer position
|
|
else
|
|
mov [bx].pos,di ; reset buffer position
|
|
endif
|
|
|
|
ebufdone:
|
|
mov emitrecordtype,0
|
|
hRet
|
|
|
|
hEndp
|
|
|
|
; edump
|
|
;
|
|
; Save:
|
|
; bx = obj file descriptor pointer
|
|
; ax = (checksum,outputbyte)
|
|
; cx = possible count
|
|
; si = emit buffer position
|
|
|
|
edump: push ax
|
|
push cx
|
|
push bx ; save src file descriptor pointer
|
|
ifdef MSDOS
|
|
push ds
|
|
mov cx,[bx].siz
|
|
mov ax,[bx].ofh
|
|
lds dx,[bx].buf
|
|
mov bh,40h
|
|
xchg ax,bx
|
|
ifdef CPDOS
|
|
push bx ; file handle
|
|
push ds ; buffer (selector)
|
|
push dx ; buffer (offset)
|
|
push cx ; # bytes to read
|
|
mov ax,@data
|
|
push ax ; reply area (selector)
|
|
mov ax,offset rarea
|
|
push ax ; reply area (offset)
|
|
call DosWrite
|
|
else
|
|
int 21h
|
|
endif
|
|
pop ds
|
|
|
|
ifdef CPDOS
|
|
or ax,ax
|
|
mov ax,rarea
|
|
jnz writerr
|
|
else
|
|
jc writerr
|
|
endif
|
|
pop bx
|
|
push bx
|
|
cmp ax,[bx].siz
|
|
je writeok
|
|
writerr:
|
|
mov objerr,-1
|
|
writeok:
|
|
else
|
|
push [bx].siz
|
|
push [bx].buf
|
|
push [bx].ofh
|
|
call write ; write (ofh,buf,siz)
|
|
add sp,6
|
|
pop bx ; need to get bx back.
|
|
push bx ; write trashes it. -Hans
|
|
cmp ax,[bx].siz
|
|
je writeok
|
|
mov objerr,-1
|
|
writeok:
|
|
mov ax,ds
|
|
mov es,ax
|
|
cld ; in case
|
|
endif
|
|
pop bx
|
|
mov ax,[bx].siz
|
|
dec ax
|
|
mov [bx].cnt,ax ; reset buffer position
|
|
ifdef MSDOS
|
|
mov di,word ptr [bx].buf ; di = start of buffer
|
|
else
|
|
mov di,[bx].buf ; di = start of buffer
|
|
endif
|
|
pop cx
|
|
pop ax
|
|
ret
|
|
|
|
endif ;M8086OPT
|
|
|
|
|
|
|
|
|
|
hProc <fMemcpy near>, <uses si di>, pDest:dword, pSource:dword, cb:word
|
|
|
|
mov cx,cb
|
|
jcxz fM1
|
|
|
|
mov dx,ds
|
|
lds si,pSource
|
|
les di,pDest
|
|
shr cx,1
|
|
rep movsw
|
|
jnc fM01
|
|
movsb
|
|
fM01:
|
|
mov ds,Dx
|
|
fM1:
|
|
hRet
|
|
hEndp
|
|
|
|
|
|
ifdef M8086OPT
|
|
; Native code version of symsrch as in asmsym.c
|
|
|
|
hProc <symsrch near>, <uses si di>
|
|
|
|
mov si,naim
|
|
xor Dx,Dx
|
|
cmp byte ptr[si-1],dl
|
|
jne sy001
|
|
jmp sy99
|
|
sy001:
|
|
mov Ax,word ptr[si-3]
|
|
mov Cx,TSYMSIZE
|
|
div Cx
|
|
|
|
mov Bx,Dx ;index into hash table
|
|
shl Bx,1
|
|
shl Bx,1
|
|
mov Ax,SEG tsym
|
|
mov Es,Ax
|
|
les di,dword ptr es:[Bx].tsym
|
|
mov Ax,es
|
|
or Ax,Ax ;if segment 0
|
|
jne sy002
|
|
jmp sy991
|
|
sy002:
|
|
mov Ax,word ptr[si-3]
|
|
mov Dx,si
|
|
xor Cx,Cx
|
|
jmp short syLook
|
|
|
|
alignCode
|
|
syNext:
|
|
les di,es:[di] ; next symbol
|
|
mov Bx,es
|
|
or Bx,Bx ; continue if segment not 0
|
|
jnz sylook
|
|
jmp sy99
|
|
syLook:
|
|
mov bx,es:[di].12 ; pointer to name
|
|
cmp Ax,es:[Bx] ; check hash values
|
|
jne syNext
|
|
|
|
xchg Bx,di
|
|
mov cl,[si-1] ; lenght to cl
|
|
inc Cx
|
|
inc di
|
|
inc di ; skip hash
|
|
repz cmpsb ; check actual strings
|
|
mov di,Bx ; restore pointers
|
|
mov si,Dx
|
|
jnz syNext
|
|
|
|
syFound:
|
|
cmp byte ptr es:[bx].1bH,12 ; if (p->symkind == CLABEL)
|
|
jne @F
|
|
|
|
@@:
|
|
mov cx,iProcCur
|
|
jcxz noNest
|
|
|
|
push ax
|
|
cmp byte ptr es:[bx].1bH,2 ; if (p->symkind == CLABEL)
|
|
jne sy1
|
|
mov Ax,word ptr es:[bx].22h ; if (p->iProc)
|
|
sy01:
|
|
or ax,ax
|
|
jz noNest0
|
|
cmp cx,Ax ; if (p->iProc != iProcCur)
|
|
je noNest0
|
|
pop ax
|
|
xor cx,cx
|
|
jmp syNext
|
|
sy1:
|
|
cmp byte ptr es:[bx].1bH,6 ; if (p->symkind == EQU)
|
|
jne noNest0
|
|
mov Ax,word ptr es:[bx].1eh ; AX = p->csassume
|
|
jmp sy01
|
|
|
|
noNest0:
|
|
pop ax
|
|
|
|
noNest:
|
|
mov word ptr symptr,Bx
|
|
mov word ptr symptr+2,es
|
|
mov Ax,1
|
|
cmp crefing,al
|
|
je syCref
|
|
hRet ;Return true
|
|
syCref:
|
|
push Ax ;call crefing routines
|
|
call crefnew
|
|
call crefout
|
|
mov al,1
|
|
jmp short sy991
|
|
sy99:
|
|
xor Ax,Ax
|
|
sy991:
|
|
hRet
|
|
|
|
hEndp
|
|
|
|
endif ;M8086OPT
|
|
|
|
ifdef M8086OPT
|
|
|
|
;int PASCAL iskey (table)
|
|
|
|
hProc <iskey near>, <uses si di>, table:dword
|
|
hLocal l1:word, l2:word
|
|
|
|
|
|
|
|
cld
|
|
mov si,naim
|
|
cmp caseflag,1 ;if (caseflag == CASEL) {
|
|
jne noComputeHash
|
|
|
|
xor Dx,Dx ;nhash = 0;
|
|
|
|
;|*** for (uc = mapstr, lc = str; *lc; )
|
|
|
|
push ds
|
|
pop es
|
|
mov di,OFFSET mapstr
|
|
xor bh,bh
|
|
mov ah,bh
|
|
alignCode
|
|
$F791:
|
|
lodsb
|
|
or al,al
|
|
jz $L2001
|
|
mov bl,al
|
|
mov al,BYTE PTR _asmcupper_[bx]
|
|
stosb
|
|
add Dx,Ax
|
|
jmp short $F791
|
|
$L2001:
|
|
|
|
;|*** *uc = 0;
|
|
|
|
stosb ;0 terminate string
|
|
|
|
;|*** uc = mapstr;
|
|
|
|
mov si,OFFSET mapstr
|
|
mov Cx,di
|
|
sub Cx,si ;cb of string into Cx
|
|
mov Ax,Dx ;hash to Ax
|
|
jmp SHORT storeNhash ;Ax has computed hash
|
|
|
|
noComputeHash:
|
|
|
|
xor cx,cx
|
|
mov cl,[si-1]
|
|
inc Cx ;include NULL
|
|
mov ax,[si-3]
|
|
|
|
storeNhash:
|
|
mov l1,ax ;nhash
|
|
mov l2,Cx ;cb
|
|
|
|
;|*** for (p = table->kttable[nhash % table->ktsize]; p; p = p->knext)
|
|
|
|
les bx,table
|
|
mov di,es:[bx] ;es now contains symbol table segment
|
|
cwd
|
|
idiv WORD PTR es:[bx+2]
|
|
shl dx,1
|
|
add di,dx
|
|
mov Bx,si ;save uc name
|
|
|
|
alignCode
|
|
isLook:
|
|
cmp word ptr es:[di],0
|
|
je isNotFound
|
|
mov di,es:[di]
|
|
|
|
;|*** if ((nhash == p->khash) && (!strcmp (p->kname,uc)))
|
|
|
|
mov Ax,l1 ;nhash
|
|
cmp es:[di+4],Ax
|
|
jne isLook
|
|
|
|
; do an inline string compare
|
|
|
|
mov Dx,di ; save p
|
|
|
|
mov Cx,l2 ;cB
|
|
mov di,WORD PTR es:[di+2] ;Es:di = p->kname
|
|
|
|
repe cmpsb ; compare while equal
|
|
|
|
jcxz isFound
|
|
|
|
mov di,Dx ;restore registers
|
|
mov si,Bx
|
|
|
|
jmp isLook
|
|
|
|
;|*** return (p->ktoken);
|
|
|
|
isFound:
|
|
mov di,Dx
|
|
mov Ax,es:[di+6]
|
|
jmp SHORT isReturn
|
|
|
|
isNotFound:
|
|
alignCode
|
|
mov ax,-1
|
|
isReturn:
|
|
hRet
|
|
hEndp
|
|
|
|
endif ;M8086OPT
|
|
|
|
|
|
ifdef M8086OPT
|
|
hProc <skipblanks near>
|
|
|
|
mov bx,lbufp
|
|
dec bx
|
|
alignCode
|
|
ik1: ; skip leading white space
|
|
inc bx
|
|
mov al,[Bx]
|
|
cmp al,' '
|
|
je ik1
|
|
cmp al,9
|
|
je ik1
|
|
|
|
mov lbufp,bx
|
|
|
|
hRet
|
|
|
|
hEndp
|
|
endif
|
|
|
|
MC struc ;structure for macro call, see asm86.h for full comments
|
|
|
|
pTSHead dd ?
|
|
pTSCur dd ?
|
|
|
|
flags db ?
|
|
iLocal db ?
|
|
cbParms dw ?
|
|
locBase dw ?
|
|
countMC dw ?
|
|
|
|
pParmNames dw ?
|
|
pParmAct dw ?
|
|
|
|
svcondlevel db ?
|
|
svlastcond db ?
|
|
svelseflag db ?
|
|
db ?
|
|
rgPV dw ?
|
|
MC ends
|
|
|
|
|
|
|
|
ifdef M8086OPT
|
|
|
|
leOverflow2:
|
|
pop ax
|
|
|
|
leOverflow:
|
|
push ss
|
|
pop ds
|
|
xor Ax,Ax
|
|
stosb ; terminate line
|
|
|
|
mov ax, 100 ; E_LTL
|
|
push AX ; print error message
|
|
call ERRORC
|
|
jmp leFin2
|
|
|
|
|
|
; fast version to expand macro bodies / coded in C in asmirp.c
|
|
|
|
hProc <lineExpand near>, <uses si di>, pMC:word, pMacroLine:dword
|
|
assume es:@data
|
|
|
|
ifdef BCBOPT
|
|
mov fNoCompact, 0
|
|
endif
|
|
mov cbLeft, 511 ; LBUFMAX (asm86.h) - 4
|
|
les si,pMacroLine ; get pointer to macro prototype
|
|
mov bx,pMC
|
|
|
|
mov dl,[bx].iLocal ; dl: local base index
|
|
mov dh,080H ; dh: local base with high bit set
|
|
add dh,dl
|
|
|
|
lea bp,[bx].rgPV ; bp: pointer to actual arg array
|
|
mov di,offset lbuf ; si: pointer to new line
|
|
|
|
push ds
|
|
mov Ax,Es
|
|
mov ds,Ax ; set seg regs for ds:si & es:di
|
|
pop es
|
|
xor ah,ah
|
|
xor ch,ch ; set loop invariate
|
|
le1:
|
|
lodsb ; fetch next prefix
|
|
test al,080H ; check for parm
|
|
jnz leParmFound
|
|
|
|
mov cl,al
|
|
jcxz leFinished
|
|
sub es:[cbLeft],ax
|
|
jc leOverflow
|
|
|
|
repz movsb ; move non parameter entry
|
|
jmp le1
|
|
|
|
leParmFound: ; argment found
|
|
mov bl,al ; compute index
|
|
shl bx,1
|
|
shl bx,1
|
|
and bx,01FFH ; remove shifted high bit
|
|
add Bx,Bp
|
|
|
|
push ds
|
|
push es
|
|
pop ds ; save current ds and set to near
|
|
|
|
cmp al,dh ; determine parm type
|
|
jae leLocalFound
|
|
|
|
mov Bx,word ptr[Bx] ; fetch pointer to actual
|
|
xchg Bx,si ; save pMacroLine
|
|
|
|
lodsb
|
|
mov cl,al
|
|
jcxz leNullArg
|
|
sub cbLeft,ax
|
|
jnc le2
|
|
jmp leOverflow2
|
|
|
|
le2:
|
|
repz movsb ; move parameter entry
|
|
leNullArg:
|
|
mov si,Bx ; restore saved pMacroLine
|
|
pop ds
|
|
xor ah, ah
|
|
jmp le1
|
|
|
|
leLocalFound:
|
|
cmp word ptr[Bx],0 ; check to see if the local
|
|
jz leBuildLocal ; is defined
|
|
|
|
leLocalMove:
|
|
xchg Bx,si ; save pMacroLine
|
|
sub cbLeft,6
|
|
jnc le3
|
|
jmp leOverflow2
|
|
|
|
le3:
|
|
mov Ax,'??' ; store leading ??
|
|
stosw
|
|
movsw ; and then remaining xxxx
|
|
movsw
|
|
jmp leNullArg
|
|
leBuildLocal:
|
|
push Dx ; call runtime helper to generate name
|
|
push Bx
|
|
push Es
|
|
xor ah,ah
|
|
sub al,dh
|
|
|
|
mov Bx,Sp ; fetch pMC
|
|
mov Bx,[Bx+8+4+4]
|
|
add Ax,[Bx].locBase
|
|
xor Bx,BX
|
|
|
|
push Bx ; offsetAscii((long) .. )
|
|
push Ax
|
|
call offsetAscii
|
|
|
|
pop Es
|
|
pop Bx
|
|
pop Dx
|
|
|
|
mov Ax,objectascii ; copy 4 byte local name to cach
|
|
mov [Bx],AX
|
|
mov Ax,objectascii+2
|
|
mov [Bx].2,AX
|
|
jmp leLocalMove
|
|
|
|
leFinished:
|
|
mov ax,es ; restore ds
|
|
mov ds,ax
|
|
leFin2:
|
|
mov linebp,di ; set linebp
|
|
mov si,offset lbuf
|
|
mov lbufp,si ; lbufp= lbuf
|
|
sub di,si
|
|
mov cx, di
|
|
mov linelength, al ; linelength = linbp - lbuf
|
|
|
|
cmp fNeedList,0 ;for listing copy to list buffer
|
|
je @F
|
|
mov di,offset linebuffer
|
|
shr cx,1
|
|
rep movsw
|
|
rcl cx,1
|
|
rep movsb
|
|
@@:
|
|
.8086
|
|
hRet
|
|
|
|
|
|
|
|
ifndef MSDOS
|
|
.286
|
|
endif
|
|
hEndp
|
|
|
|
endif ;M8086OPT
|
|
|
|
ifdef M8086OPT
|
|
|
|
;*** expandTM - expand text macro in naim in lbuf/lbufp
|
|
;*
|
|
;* expandTM (equtext);
|
|
;*
|
|
;* Entry equtext = replacement string
|
|
;* naim = text macro
|
|
;* begatom = first character in lbuf to replace
|
|
;* endatom = first character in lbuf after string to replace
|
|
;* Exit lbuf = new line to be parsed
|
|
;* Returns
|
|
;* Calls
|
|
;* Note Shifts characters from lbufp to make substitution of TM.
|
|
;* Inserts replacement string at begatom
|
|
;*/
|
|
|
|
hProc <expandTM near>, <uses si di>, equtext:word
|
|
hLocal cbEndatom:word, cbNaim:word, cbText:word, fShifted:byte
|
|
|
|
cld ; String instructions go forward
|
|
|
|
mov ax, ds ; Set es to @data
|
|
mov es, ax ;
|
|
|
|
xor ax, ax ; Will stop scanning when [di] == [al] == 0
|
|
mov fshifted, 0 ; Haven't shifted line yet
|
|
|
|
mov cx, linebp ; Calculate cbEndatom == strlen(endatom)
|
|
sub cx, endatom ; but use (linebp - endatom + 1) as method
|
|
inc cx ;
|
|
mov cbEndatom, cx ; Store result in cbEndatom
|
|
|
|
mov cx, endatom ; Calculate cbNaim == strlen(naim)
|
|
sub cx, begatom ; but use (endatom - begatom) as method
|
|
mov cbNaim, cx ; Store result in cbNaim
|
|
|
|
mov di, equtext ; Calculate cbText == strlen(equtext)
|
|
mov cx, -1 ;
|
|
repne scasb ;
|
|
not cx ; [cx] == length of equtext
|
|
dec cx ; don't count NULL
|
|
mov cbText, cx ; Store result in cbText
|
|
|
|
cmp cbNaim, cx ; Q: Is replacement longer than name?
|
|
jl shiftline ; Y: Must shift endatom string to the right
|
|
|
|
copytext:
|
|
mov di, begatom ; Copy replacement text into lbuf
|
|
mov si, equtext ;
|
|
mov cx, cbText ; Number of bytes to copy
|
|
shr cx, 1 ;
|
|
rep movsw ;
|
|
jnc etm2 ;
|
|
movsb ;
|
|
etm2:
|
|
cmp fShifted, 0 ; Q: Have already shifted line right?
|
|
jne etmEnd ; Y: Done
|
|
|
|
mov si, endatom ; Q: Is cbNaim == cbText?
|
|
cmp di, si ;
|
|
je etmEnd ; Y: Done
|
|
|
|
mov cx, cbEndatom ; N: Must shift endatom string left
|
|
shr cx, 1 ;
|
|
rep movsw ;
|
|
jnc etm3 ;
|
|
movsb ;
|
|
etm3:
|
|
mov linebp, di ;
|
|
jmp etmEnd ; Done
|
|
|
|
|
|
shiftline: ; Shift string at endatom to right
|
|
|
|
mov cx, cbEndatom ; Number of bytes to move
|
|
mov si, linebp ; [si] = end of string in lbuf
|
|
mov di, si ;
|
|
add di, cbText ;
|
|
sub di, cbNaim ; di == si + amount to shift string right
|
|
mov linebp, di ;
|
|
|
|
mov dx, di ; check if line too long
|
|
sub dx, OFFSET lbuf ;
|
|
cmp dx, 512 ; LBUFMAX (asm86.h)
|
|
jge eltl ; line too long
|
|
|
|
std ; String instructions go backwards
|
|
rep movsb ; Shift line
|
|
inc fShifted ;
|
|
cld ; String instructions go forward again
|
|
jmp copytext ;
|
|
|
|
eltl:
|
|
mov ax,100 ; Error E_LTL Line too long
|
|
push ax ;
|
|
call ERRORC ;
|
|
mov di, begatom
|
|
mov byte ptr [di], 0 ; Truncate line
|
|
|
|
etmEnd:
|
|
mov ax, begatom ; Reset lbufp to point to start of next
|
|
mov lbufp, ax ; token
|
|
|
|
hRet
|
|
hEndp
|
|
|
|
endif ;M8086OPT
|
|
|
|
|
|
ifdef MSDOS
|
|
ifdef M8086OPT
|
|
|
|
;*** farwrite - write with far buffer
|
|
; farwrite(ofh,buf,count);
|
|
|
|
hProc <farwrite far>, handle:word, buffer:dword, count:word
|
|
|
|
mov ax,handle
|
|
mov cx,count
|
|
push ds
|
|
lds dx,buffer
|
|
mov bh,40h ; write
|
|
xchg ax,bx
|
|
ifdef CPDOS
|
|
push bx ; file handle
|
|
push ds ; buffer (selector)
|
|
push dx ; buffer (offset)
|
|
push cx ; # bytes to read
|
|
mov ax,@data
|
|
push ax ; reply area (selector)
|
|
mov ax,offset rarea
|
|
push ax ; reply area (offset)
|
|
call DosWrite
|
|
else
|
|
int 21h
|
|
endif
|
|
pop ds
|
|
ifdef CPDOS
|
|
or ax,ax
|
|
mov ax, word ptr rarea
|
|
jnz fwriterr
|
|
else
|
|
jc fwriterr
|
|
endif
|
|
cmp ax,count
|
|
je fwriteok
|
|
fwriterr:
|
|
mov objerr,-1
|
|
fwriteok:
|
|
hRet
|
|
|
|
hEndp
|
|
endif ;M8086OPT
|
|
endif
|
|
|
|
|
|
|
|
|
|
;*** farAvail ()
|
|
|
|
ifdef MSDOS
|
|
ifndef CPDOS
|
|
|
|
hProc <farAvail far>
|
|
|
|
or Bx,0FFFFH ;request max memory from dos
|
|
mov ah,48H ;paragraphs left in Bx
|
|
int 21H
|
|
|
|
mov ah,48H ;then allocate it
|
|
int 21H
|
|
jnc noMem
|
|
xor Bx,Bx
|
|
noMem:
|
|
mov Ax,16
|
|
cwd
|
|
mul Bx ;return paragraphs * 16
|
|
hRet
|
|
|
|
hEndp
|
|
|
|
endif
|
|
endif
|
|
|
|
|
|
end
|