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

📄 asm.asm

📁 比dos下的debug更好的debug程序源码
💻 ASM
📖 第 1 页 / 共 3 页
字号:
	lodsb			;consume the bracket
	mov	al,[di+asmop.areg1] ;see if any segment reg
	cmp	al,0ffh
	jz	brklp		; none
	mov	[di + asmop.areg1],0ffh ; set it back
	sub	ah,ah
	bts	[PrefixBitmapWord],ax	; set the prefix bit
brklp:
	call	wadespace	;get next string
	jz	brackerr	;found CR before closing bracket
	cmp	al,'+'		;see if plus sign
	jne	brnp		;might mean bracket-not-plus
	inc	si		;else move past plus sign
	call	wadespace	;and find next
	jz	brackerr	;oops, no closing bracket

;We have ignored any plus sign if it was there

brnp:
	cmp	al,'-'		;is it a minus sign?
	je	brmem		;if so, must be a value?
	cmp	al,']'		;if not, closing bracket already?
	je	brackx		;if so, go exit
	push	di		;save pointer to buffer
	mov	di,offset arg4	;point to arg4 for base-mode reg gathering
	call	parsereg	;see if a register?
	pop	di		;restore buffer pointer

;parsereg cannot return CY, and does no bracket check anyway. No idea why 
;this line is even here

	jc	brackerr	; if invalid fp or CRDRTR reg num
	jz	brreg		;ZF means we found a register
brmem:
	call	parseval		;glom a number into EBX
	jc	brackerr		;get out if no number
	add	[di+asmop.addrx],ebx	;stick in as offset or segment
	call	WadeSpace		;get next
	jz	brackerr		;still no closing bracket
	jmp	brklp			;else get next bracket value

;We get here if we found a named register inside the brackets, like [bx

brreg:
	mov	[di+asmop.mode],AM_BASED	;say base reg involved
	mov	ah,[arg4.areg1]		;get which register it is
	mov	bl,[arg4.asize]		;and width of register
	test	[di+asmop.msize],0FFh	;see if anything assigned yet
	jz	notszyet		;nope, not yet
	cmp	[di+asmop.msize],bl	;ok, bl is the size
	jnz	brackerr		;mismatch, I guess???
notszyet:
	mov	[di+asmop.msize],bl	;else set the size
	call	WadeSpace
	cmp	al,'*'			;multiply operation
	jne	notscale		;nope, no scaling
	cmp	bl,DWORDSIZE		;else dword scaling?
	jne	brackerr		;must be dword reg for multiply?
	inc	si			;move past *
	call	WadeSpace		;find next
	sub	al,'0'			;last char returned, cvt to decimal?
	cmp	al,TIMES1		;*1 is OK
	je	brackok1
	cmp	al,TIMES2		;*2 is OK
	je	brackok1
	cmp	al,TIMES4		;*4 is OK
	je	brackok1
	cmp	al,TIMES8		;*8 is OK
	jne	brackerr		;else, can't do it
brackok1:
	inc	si			;bump SI past scaling factor
	mov	byte ptr [di+asmop.ascale],al	;and set factor in struct
reg2x:
	test	[di+asmop.areg2],0FFh	;initialized to FF
	jns	brackerr		;so bit 7 better be set
	mov	[di+asmop.areg2],ah	;if so stick areg1=reg into it
	jmp	brklp			;get next thing inside brackets

;Found a register that was NOT followed by a scaling factor. The magic code
;for the found register is in AH. We stick this register into areg1 unless
;areg1 is already in use, in which case we stick it in areg2.

notscale:
	test	[di+asmop.areg1],0FFh	;has reg been assigned yet?
	jns	reg2x			;if not, stick reg into areg2
	mov	[di+asmop.areg1],ah	;else, stick reg into areg1
	jmp	brklp

;OK, we found the closing bracket.  Presumably everything between brackets
;was kosher. We also get here with the construct [], with nothing in there.

brackx:
	cmp	[di+asmop.msize],DWORDMODE	;addressing mode size=32?
	jne	brackn32			;if not, skip
	or	[PrefixBitmapWord],AS_ADDRSIZE	;else set addrsize prefix flag
brackn32:
	inc	si				;move past ]
	cmp	[di+asmop.mode],AM_NONE		;see if empty
	Jne	gaxc				;if not, cool
	mov	[di+asmop.mode],AM_MEM		;else set mode to memory
	mov	[di+asmop.msize],WORDMODE	;see if word mode
	test	[di+asmop.addrx],NOT 0FFFFH	;see if any address
	jz	gaxc				;if not, skip out
	or	[PrefixBitmapWord],AS_ADDRSIZE	;else set for ???
	mov	[di+asmop.msize],DWORDMODE	;and say dword assumed??
	jmp	gaxc				;and jmp
brackerr:
	stc
	ret
parsearg	ENDP

; Parse possible control register reference
;
; INPUT: SI points to buffer containing this argument (a string)
; OUTPUT: For this arg, the mode and areg1 fields of the structure are
;	filled in.
;	NZ if we can't recognize the register
;	CY if index for register is out of range
; PROCESSING: Look for any control reg, debug reg, FP reg or TR reg. The
;	TR regs are the Appendix H test registers.
;		Beyond this, we allow up to 8 of each of the ST, CR and DR
;	even though there is no DR1 or DR2, nor any CR4,5,6 or 7. I guess
;	these exist in opcode space, just not in the CPU!
;
parsecontrol	PROC
	mov	ax,word ptr [si]
	mov	cl,AM_CR
	cmp	ax,"rc"			;Control register CRx
	je	gotcontrol
	mov	cl,AM_DR
	cmp	ax,"rd"			;Debug register DRx
	je	gotcontrol
	mov	cl,AM_TR
	cmp	ax,"rt"			;Test registers, Appendix H
	je	gotcontrol
	cmp	ax,"ts"			;ST(x for FP
	je	gotfpreg
	or	al,1
	ret

;Um. There are 8 each of the debug registers and FP stack registers, although
;DR1 and DR2 don't exist.  There are only 4 control registers, and I can't
;find any reference at all to any TRx registers.


gotcontrol:
	lodsw				;grab control reg 1st 2 chars
	lodsb				;and number
	sub	al,'0'			;convert to binary
	jc	gcerrx			;oops, below 0
	cmp	al,8			;see if register 8 or above
	jae	gcerrx			;error if so
	mov	[di+asmop.mode],cl	;save CL 
	mov	[di+asmop.areg1],al	;save which one
	sub	ax,ax			;set ZF
	ret
gcerrx:
	stc     
	ret
gotfpreg:
	lodsw				;consume the 'ST'
	call	wadespace		;find next 
	cmp	al,'('			;is it (
	jne	asmgotch		;if not, check for NASM syntax
	inc	si			;bump past (
	call	wadespace		;find next
	push	ax			;stack the char found
	inc	si			;move past it
	call	wadespace		;find the next
	cmp	al,')'			;end of stack reference?
	pop	ax			;restore char between ()
	jne	badfpreg		;no close, so bitch

;We get here in two cases: we found (x), or we didn't find (
;In the first case, x is in AL, in the second, AL has what we found instead
;By implication, we accept either ST(x) or STx

asmgotch:
	inc	si			;move to next position anyway
	sub	al,'0'			;convert to binary
	jc	badfpreg		;must be some number
	cmp	al,8			;else see if in range
	jae	badfpreg		;if >=8, out of range
	mov	[di+asmop.mode],AM_FPREG	;set flag for FP
	mov	[di+asmop.areg1],al	;save binary value of this reg
	sub	ax,ax			;and return ZF
	ret
badfpreg:
	stc
	ret
parsecontrol	ENDP


;
; parse a size attribute.  the PTR keyword is optional.
;
; INPUT: SI points to buffer containing this argument (a string)
; OUTPUT: bl has size
;         CY set if error ins size
parsesize	PROC
	mov	ax,[PrefixBitmapWord]	;get bitmap into AX
	call	isbyte			;chk buffer for 'byte'
	mov	bl,BYTESIZE		;assume byte size
	jz	gotsize			;if match, fine
	call	isword			;else chk for word
	mov	bl,WORDSIZE		;assume it was
	jz	gotsize			;if so, fine
	inc	si			;go past first char (could be t)
	call	isbyte			;and check if it was 'tbyte'
	jnz	notbyte			;if not, really not a byte
	cmp	byte ptr [si-1],'t'	;else, was it a t
	mov	bl,TBYTESIZE		;assume it was a tbyte
	jz	gotsize			;yes, it was
	or	bl,bl			;else return NZ
	ret

;OK, it's not 'byte', 'word' or 'tbyte'. Maybe it's 'dword'. To get here,
;SI has been moved past the first char, so see if it is dword, qword'or fword

notbyte:
	call	isword			;check for xword
	jnz	notsize			;nope, not it
	mov	al,[si-1]		;else get that x
	cmp	al,'d'			;was it dword
	mov	bl,DWORDSIZE		;assume it was
	je	gotsize			;yep, got it
	cmp	al,'q'			;was it qword
	mov	bl,QWORDSIZE		;assume it was
	je	gotsize			;yep, that's it
	cmp	al,'f'			;how about fword
	mov	bl,FWORDSIZE		;assume that
	je	gotsize			;yes
notsize:
	dec	si			;back to beginning of string
	or	bl,1			;set NZ
	ret
gotsize:
	mov	[di+asmop.asize],bl	;set requested size
	add	si,4			;move past string in buffer

;By implication here, it is legal to type 'ptr' as many times as you want.
;You can say mov word ptr ptr ptr ptr ptr [44],5

gs2:
	call	wadespace		;find next nonspace
	jz	operrx			;didn't find, so error
	cmp	al,'['			;'ptr' is optional, so chk bracket
	je	opok			;if so, fine
	push	si			;else look for 'ptr'
	push	di
	mov	cx,3
	mov	di,offset say_ptr
	repe	cmpsb
	pop	di
	pop	si
	clc
	jnz	opok			;if not, we're ok
	add	si,3			;else skip wasted 'ptr'
	jmp	gs2			;
operrx:
	stc
opok:
	ret
parsesize	ENDP

; compare input string with 'byte'
;
; INPUT: SI points to buffer containing this argument (a string)
; OUTPUT: ZF if the argument is 'byte' NZ otherwise
; PROCESSING: Simply compare
; NOTE: AX must be preserved
;
isbyte 	PROC
	push	si
	push	di
	mov	cx,4
	mov	di, offset say_byte
	repe	cmpsb
	pop	di
	pop	si
	ret
isbyte	endp
;
; compare input string with 'word'
;
; INPUT: SI points to buffer containing this argument (a string)
; OUTPUT: ZF if we matched 'word', else NZ
; PROCESSING: just compare
;	AX cannot be modified
;
isword 	PROC
	push	si
	push	di
	mov	cx,4
	mov	di, offset say_word
	repe	cmpsb
	pop	di
	pop	si
	ret
isword	endp

;
; INPUT: SI points to buffer containing this argument (a string)
; OUTPUT: CY if bad segment argument
;	ZF if good segment argument on its own
;		In this case, mode and size are set
;	SF if valid segment is followed by [
; PROCESSING: 
;	1) See if string matches list of seg names, return NZ if not
;	2) See if segment is only arg (like mov ax,cs. If so, return ZF
;	3) Else, see if it is seg:[ and if so, return SF
;	4) Else return carry, bad segment argument
;
parseseg	PROC
	mov	cx,6	  		;6 possible segments by name
	push	di			;save ptr to struct
	mov	di,offset psegs		;names of registers
	lodsw				;get what user entered
	repne	scasw			;find it in the strings list
	pop	di			;restore struct ptr
	jz	gotseg			;found a match
	sub	si,2			;not a seg, undo the lodsw
	ret				;return NZ

;Here we have a significant departure from debug.exe syntax.  If you want
;a segment override in debug, you must put the override like CS: or ES:
;on a separate line, and the remainder on the next line.  Debug requires you
;to say:
;xxxx:xxxx cs:
;xxxx:xxxx mov al,[44]
;
;Here you are NOT allowed to do this.  Instead, you must enter:
;xxxx:xxxx mov al,cs:[44]
;
;an earlier part of the program also accepted:
;
;xxxx:xxxx cs:mov al,[44]
;

gotseg:
	sub	cx,6			;sub starting value
	not	cx			;convert to index
	mov	[di+asmop.areg1],cl	;save that index in areg1
	call	wadespace		;find next non-0
	jz	segalone		;if nothing, fine, just seg
	cmp	al,':'			;else chk for colon
	jne	segalone		;if not, we just got the segment
	inc	si			;bump past colon
	call	wadespace		;find next stuff
	jz	segerr			;nothing else is error
	cmp	al,'['	 		;do we have a fixed address next?
	jne	segerr			;if not, real trouble
	or	al,80h			;else return SF
	ret
segalone:
	mov	[di+asmop.mode],AM_SEG	;say mode is just a segment
	mov	[di+asmop.asize],WORDSIZE	;so size is 2 (all segregs are word)
	sub	ax,ax			;return ZF
	ret
segerr:
	stc				;error so return CY
	ret
parseseg	ENDP

;
; parse a register name
;
; INPUT: SI points to input being parsed
;	DI points to structure for this argument, or to arg4 if we are
;	inside brackets.
; OUTPUT: ZF if reg found, and mode and size set
;	NZ if not a name
; PROCESSING: parse for all register names, set size and mode if found any,
;	else return NZ if not found
;NOTES:
;	1) If a register name was found, SI was bumped past it, else SI
;	   remained unmodified
;	2) At least one caller to this routine checks the carry. I can't
;	   find anything in here that would set or clear the carry as a
;	   return value...	
;
parsereg	PROC
	mov	bl,2			;set word size
	cmp	byte ptr [si],'e'	;is first char an e
	jne	nextreg			;if not, fine
	mov	bl,4			;else set dword size
	inc	si			;and move past the e
nextreg:
	lodsw				;get next 2 bytes
	mov	cx,16			;there are 16 2-char strings for regs
	push	di			;save di
	mov	di,offset regs		;to scan list of reg names
	repne	scasw
	pop	di
	jz	gotreg			;if ZF, we hit a match
	sub	si,2			;else back to beginning of input
	cmp	bl,4			;unless we moved past an e
	jnz	nextreg2		;if bl=4, we did
	dec	si			;so back up to first char
nextreg2:
	or	si,si			;set NZ
	ret				;since not a reg

;It just so happens that the regs string has 16 2-char entries, the first 8
;are byte registers and the last 8 are word registers

gotreg:
	xor	cl,15			;really, how about 0Fh?
	mov	[di+asmop.asize],BYTESIZE	;say byte arg
	cmp	cx,8			;if found in positions 0-7
	jb	gr1			;then it was a byte
	mov	[di+asmop.asize],bl	;else word or dword depending on e
gr1:
	and	cl,7		   	;get mod8 for index
	mov	[di+asmop.areg1],cl	;and save that
	mov	[di+asmop.mode],AM_REG	;say a reg asked for by name
	sub	ax,ax			;return ZF
	ret
	
parsereg	ENDP
;
; Make sure that the next string is a number, and return in EBX if so
;
; INPUT: SI points to string to be parsed
; OUTPUT: NC if we find a number
;	EBX contains that number (0=extended if required)
;	CY if not a number, or not found???
; PROCESSING: DI points to the argument structure being built, and must
;	be preserved.
;NOTES: ReadNumber simply assumes that all bytes in the input buffer are
;	hex values up to some special character like space, comma, colon
;	or CR. So ReadNumber cannot return an error. In this case, we
;	already know that we have no named register at [si], which is
;	a good thing, because if we did, ReadNumber would return the
;	current contents of that logical register.
;
parseval	PROC
	call	wadespace	;find arg string
	jz	noval		;oops, not there
	push	di		;else save location
	call	ReadNumber	;read a number into eax
	pop	di		;restore pointer
	mov	ebx,eax		;return number in ebx
	ret
noval:
	stc
	ret
parseval	ENDP
end

⌨️ 快捷键说明

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