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

📄 asmops.asm

📁 比dos下的debug更好的debug程序源码
💻 ASM
📖 第 1 页 / 共 3 页
字号:
;                     
; GRDB
;
; Copyright(c) LADsoft
;
; David Lindauer, camille@bluegrass.net
;
;
; ASMOPS.ASM
;
; Function: Assembler operand parsers
;
	;MASM MODE
	.MODEL SMALL
	.386

include iasm.inc
include easm.inc
include iopcodes.inc
include eopcodes.inc
include eopcom.inc
include eprints.inc 
include einput.inc 
include emtrap.inc
include	edispatc.inc
include eoperand.inc
include eoptions.inc

	PUBLIC	AOP0,  AOP1,  AOP2,  AOP3,  AOP4,  AOP5,  AOP6,  AOP7
	PUBLIC	AOP8,  AOP9,  AOP10, AOP11, AOP12, AOP13, AOP14, AOP15
	PUBLIC	AOP16, AOP17, AOP18, AOP19, AOP20, AOP21, AOP22, AOP23
	PUBLIC	AOP24, AOP25, AOP26, AOP27, AOP28, AOP29, AOP30, AOP31
	PUBLIC	AOP32, AOP33, AOP34, AOP35, AOP36, AOP37, AOP38, AOP39
	PUBLIC	AOP40, AOP41, AOP42, AOP43, AOP44, AOP45, AOP46, AOP47
	PUBLIC	AOP48, AOP49, AOP50, AOP51, aop52, AOP53, AOP54, AOP55
	PUBLIC	AOP56, AOP57, AOP58

	.data
base16c	dw	0ff03h,0ff05h,0ff07h,0ff06h,0705h,0605h, 0703h,0603h
	dw	0ffffh,0ffffh,0ffffh,0ffffh,0507h,0506h, 0307h,0306h

	.code

;Check if arg1.asize is 4 or less.  If greater, return error to caller's
;caller by mucking with the stack.

intsize PROC
	cmp	[arg1.asize],DWORDSIZE	;maybe this means the first argument
	ja	rtnDirectlyToDispatcherWithCY	;can't exceed dword size
	ret
intsize	ENDP

;See if the mode field for this structure references a memory operand
;and return error to caller's caller if not

chkmem	PROC
	cmp	[bx+asmop.mode],AM_MEM		;this is 3
	jne	rtnDirectlyToDispatcherWithCY	;bomb if not memory operand
	ret
chkmem	ENDP

;See if the mode field for this structure references an immediate operand
;and return error to caller's caller if not

chkimm	PROC
	cmp	[bx+asmop.mode],AM_IMM		;check if immediate
	jne	rtnDirectlyToDispatcherWithCY	;if not, bomb
	ret
chkimm	ENDP

;See if the mode field for this structure references a segment
;and return error to caller's caller if not

chkseg	PROC
	cmp	[bx+asmop.mode],AM_SEG
	jne	rtnDirectlyToDispatcherWithCY
	ret
chkseg	ENDP

;This is a little more complicated. Let's hypothesize that chkregw is 
;shorthand for checking a 16-bit register type opcode. In this case,maybe the
;opcode must contain more than a single byte.  So before we check if it
;is a register-type opcode, we must make sure it has extra byte(s). So
;we stop here first, and if the length makes us happy, then we check mode
;  Next guess - if this is a byte argument, we bomb since a word register
;requires a word operand.

chkregw	PROC
	cmp	[bx+asmop.asize],BYTESIZE	;is this a byte opcode
	je	rtnDirectlyToDispatcherWithCY	;if so, bomb
	jmp	chkreg			;else check mode for register type
chkregw	ENDP

;Possibly this is used for in and out, where DX is the only register
;allowed?

chkdx	PROC
	cmp	[bx+asmop.asize],WORDSIZE	;if not a word register
	jne	rtnDirectlyToDispatcherWithCY	;then bomb
	cmp	[bx+asmop.areg1],isEDX		;else see if DX register
	jne	rtnDirectlyToDispatcherWithCY	;if not, bomb
	jmp	chkreg
chkdx	ENDP

;Not sure about the AX part of this, since all that is being checked is
;a size of byte

chkaxw	PROC
	cmp	[bx+asmop.asize],BYTESIZE	;if a byte register
	je	rtnDirectlyToDispatcherWithCY	;then bomb
chkaxw	ENDP

;This IS a check for AX (actually, 0 is EAX)

chkax	PROC
	cmp	[bx+asmop.areg1],0	    	;if not EAX (maybe AX or AL)
	jne	rtnDirectlyToDispatcherWithCY	;then bomb
chkax	ENDP

;Check for a register?  As opposed to ??

chkreg	PROC
	cmp	[bx+asmop.mode],AM_REG		;is this flag set?
	jne	rtnDirectlyToDispatcherWithCY	;if not, bomb
	ret
chkreg	ENDP

;We bomb if arg3.mode isn't none, and if it is, we still bomb if arg2.mode
;is none.  So arg3 is required to have a 'mode', whatever that is, I guess

noarg3	PROC
	cmp	[arg3.mode],AM_NONE
	jne	rtnDirectlyToDispatcherWithCY
	cmp	[arg2.mode],AM_NONE
	je	rtnDirectlyToDispatcherWithCY
	ret
noarg3	ENDP

;Same as above, except it applies to arg2

noarg2	PROC
	cmp	[arg2.mode],AM_NONE
	jne	rtnDirectlyToDispatcherWithCY
	cmp	[arg1.mode],AM_NONE
	je	rtnDirectlyToDispatcherWithCY
	ret
noarg2	ENDP

;Whoa, lets see here.  If arg1.mode, whatever that is, is NOT 0, we jnz to
;rtnDirectlyToDispatcherWithCY. Since this routine was called, the return 
;address is on the stack. Which means rtnDirectlyToDispatcherWithCY strips 
;off the return address, and returns to the caller's caller. 

noarg1	PROC
	cmp	[arg1.mode],AM_NONE
	jne	rtnDirectlyToDispatcherWithCY
	ret
noarg1	ENDP
;
; pops the ret address from the AOP caller
; and goes directly back to the parser with a mismatch error
;
rtnDirectlyToDispatcherWithCY	PROC
	pop	ax
	stc
	ret
rtnDirectlyToDispatcherWithCY	ENDP


;see if size of this opcode is 1. If not, we are returning NZ and AL=1. I
;assume that 1 is important, since without the OR line, we would also be
;returning NZ if the size was not 1. In fact, several callers immediately
;do a stosb, so at the very least we are ensuring an odd number???
;  Next guess: AL will eventually be used as part of the stored, assembled
;byte.  So apparently the purpose of this routine is to set bit 0 of the
;untimate assembled value if this is NOT a byte operand.

sizeb0	PROC
	cmp	[bx+asmop.asize],BYTESIZE
	je	szb0x
	or	al,1
szb0x:
	ret
sizeb0	ENDP

;In which case, the purpose of this routine is to set bit 3 of AL if the
;operand is NOT a byte operand.

sizeb3	PROC
	cmp	[bx+asmop.asize],BYTESIZE
	je	szb3x
	or	al,8
szb3x:
	ret
sizeb3	ENDP
;
; main RM handler
;
; within this routine, CX = pointer to mod/RM byte and DX = flag for
; <e>bp based indexing
;
; all MOD/RM fields are set up assuming no offset and updated 
; later...
;
asmfrm	PROC
	cmp	[bx+asmop.mode],AM_FPREG ; check for register direct mode
	jne	asmrm2
	or	al,0c0h			; modrm = 0c0+al+regval
	or	al,[bx+asmop.areg1]
	stosb
	ret
	
asmfrm	ENDP



asmrm	PROC
	shl	al,3			; shift reg val into place
asmrm	ENDP


asmrm2	PROC
;
; registers are the same in both 16 & 32-bit
;
	cmp	[bx+asmop.mode],AM_REG	; 1check for register direct mode
	jne	rmnreg
	or	al,0c0h			; modrm = 0c0+al+regval
	or	al,[bx+asmop.areg1]
	stosb
	ret
rmnreg:
	cmp	[bx+asmop.msize],DWORDMODE	; see which style of addressing
	je	asmrm32
;
; 16-bit MEM handler
;
	cmp	[bx+asmop.mode],AM_MEM	; 16 bit, check for mem
	jne	rm16nmem
	or	al,6			; MODRM = 6+al
	stosb
	jmp	rmwoffs
rm16nmem:
	cmp	[bx+asmop.mode],AM_BASED ; check for 16 bit based
	jne	rtnDirectlyToDispatcherWithCY
;
; 16-bit base handler, restricted combos and no scaling
;
	push	ax			; yes, get the reg vals
	sub	ax,ax
	mov	al,[bx+asmop.areg1]
	mov	ah,[bx+asmop.areg2]
	mov	dx,ax
	push	di			; scan for a match and to get index
	mov	di,offset base16c
	mov	cx,16
	repne	scasw
	pop	di
	pop	ax
	jnz	rtnDirectlyToDispatcherWithCY	; scan failed, exit
	bt	cx,3
	jc	rm16nswap
	xchg	dl,dh
rm16nswap:
	and	cl,7
	or	al,cl
	mov	cx,di			; cx points at modrm byte
	stosb
	jmp	rmanyoffs		; check for offs
;
; 32-bit modes start here
;
asmrm32:
	cmp	[bx+asmop.mode],AM_MEM	; 32 bit, check for mem
	jne	rm32nmem
;
; generic mem handler
;
	or	al,5			; MODRM = 5+al
	stosb
	jmp	rmwoffs
rm32nmem:
	cmp	[bx+asmop.mode],AM_BASED 	; check for based
	jne	rtnDirectlyToDispatcherWithCY	; not legal if not
	cmp	[bx+asmop.areg2],0FFh	; else see if second reg defined
	je	rm32bbonly
	cmp	[bx+asmop.areg1],0FFh	; else see if first reg defined
	je	rm32bionly
;
; both a base AND an index
;
; the parser should have checked that ESP is not the scond arg
; and that we don't have two EBP args
;
	cmp	[bx+asmop.areg1],isEBP	; check for BP based
	je	rm32bbsebp
	or	al,4			; flag MOD for SIB
	mov	cx,di
	stosb
	bsf	ax,[bx+asmop.ascale]	; calculate SIB byte
	shl	ax,3
	or	al,[bx +asmop.areg2]
	shl	ax,3
	or	al,[bx+asmop.areg1]
	stosb
	sub	dx,dx
	jmp	rmanyoffs
;
; base and index, base is ebp
rm32bbsebp:
	or	al,4
	mov	cx,di
	stosb
	bsf	ax,[bx+asmop.ascale]	; calculate SIB byte
	shl	ax,3
	or	al,[bx+asmop.areg2]
	shl	ax,3
	or	al,5			; bp based
	stosb
	mov	dx,0ff05h
	jmp	rmanyoffs
;
; index only
rm32bionly:
	or	al,4 			; select SIB byte
	stosb
	bsf	ax,word ptr [bx+asmop.ascale] ; calculate scale factor
	shl	ax,3			; shift over
	or	ax,word ptr [bx+asmop.areg2] ; add in index
	shl	ax,3			; shift over
	or	ax,5			; base = 5, that is none since mod = 0
	stosb
	mov	eax,[bx+asmop.addrx]	; always 32-bit ofs in this mode
	stosd
	ret
;
; only a base reg
;
rm32bbonly:
	; shouldn't get here if no regs
	cmp	[ebx+asmop.areg1],isESP	; only one reg, check for ESP
	je	rm32besp
	cmp	[ebx+asmop.areg1],isEBP	; only one reg, check for EBP
	je	rm32bebp
	or	al,[ebx+asmop.areg1]	; no, normal MODRM byte with no SIB
	mov	cx,di
	stosb
	mov	dh,0FFh			; pretend 16 bit
	mov	dl,al
	and	dl,7
	jmp	rmanyoffs
;
; based ESP, no index
;
rm32besp:
	or	al,4    		; select SIB byte (sib needed
	mov	cx,di			; for indexing off ESP)
	stosb
	mov	al,24h			; sib byte for [esp] mode
	stosb
	sub	dx,dx
	jmp	rmanyoffs
;
; based ebp, no index
;
rm32bebp:
	or	al,5
	mov	cx,di			; so we can adjust mod later
	stosb
	mov	dx,0ff05h		; MUST have offset, this is BP base reg
	jmp	rmanyoffs
;
; now the auto offset routine.
; if (E)BP, we ALWAYS have an offset	
; otherwise we see if the offset is zero before encoding anything
	
asmrm2	ENDP
rmanyoffs PROC
	mov	eax,[bx+asmop.addrx]	; get offs
	cmp	dx,0ff05h		; BP reg ALWAYS has offs
	je	rmaomho

	or	eax,eax 		; else no offs if offs = 0
	jz	rmaook
;
; if we get here we have an offset, fix the RM field and embed the
; offset
;
rmaomho:
	xchg	cx,bx
	add	byte ptr [bx],40h	; else set MOD field = 1
	xchg	cx,bx
	and	eax,NOT 7FH		; else see if fits in a byte
	jz	rmboffs
	cmp	eax,NOT 7fh
	je	rmboffs    		; yep, go do it
	xchg	cx,bx
	add	byte ptr [bx],40h	; else MOD field = 2
	xchg	cx,bx
	jmp	rmwoffs			; and go do it

rmboffs:
	mov	eax,[bx+asmop.addrx]	; get offs
	stosb      			; store a byte offs
rmaook:
	clc
	ret
rmanyoffs	ENDP
rmszoffs	PROC
	mov	eax,[bx+asmop.addrx]
	cmp	[bx+asmop.msize],WORDMODE
	jae	rmwoffs
	stosb
	clc
	ret
rmszoffs	ENDP
rmwoffs	PROC
	mov	eax,[bx+asmop.addrx]	; check size
	cmp 	[bx+asmop.msize],WORDMODE
	ja	rmdwoffs
	stosw				; word offs
	clc
	ret
rmdwoffs:
	test	[Disassemble32Bit],1
	jz	rtnDirectlyToDispatcherWithCY
	stosd				; dword offs
	clc
	ret
rmwoffs	ENDP
rmszimm	PROC
	mov	eax,[bx+asmop.addrx]	; check size
	cmp	[bx+asmop.asize],WORDSIZE
	jae	rmszimmw
	stosb
	clc
	ret
rmszimmw:
	jne	rmszimmd
	stosw
	ret
rmszimmd:
	cmp	[bx+asmop.asize],DWORDSIZE
	jne	rtnDirectlyToDispatcherWithCY
	test	[Disassemble32Bit],1
	jz	rtnDirectlyToDispatcherWithCY
	stosd
	ret
rmszimm	ENDP
;
; no operands. In this case, the opcode length is 1, so we go through this
;	weird locution to rep mov a single byte out of the structure and
;	into [di], wherever that points. Apparently it points into an opcode
;	buffer somewhere. If the opcode length is greater than one, what
;	happens?
;
AOP0	PROC
	call	noarg1			;see if arg1.mode=0, whatever that means
	push	si			;only return here if it IS 0
	movzx	cx,[si+opcode.oclength]	;so get the length of the opcode
	lea	si,[si+opcode.compare]	;find the opcode in the structure
	rep	movsb			;copy from structure to buffer
	pop	si			;restore pointer to structure
	clc				;say no problem
	ret
AOP0	ENDP
;
; word reg, bits 0-2 of opcode = reg num
;
AOP1	PROC
	call	noarg2
	call	intsize
	mov	bx,offset arg1
	call	chkregw
	mov	al,byte ptr [si+OPCODE.COMPARE]
	or	al,[arg1.areg1]
	stosb
	clc
	ret
AOP1	ENDP
;
; word acc,reg... reg = bits 0-2 of opcode
;
AOP2	PROC
	call	noarg3
	call	intsize
	mov	bx,offset arg1
	call	chkaxw
	mov	bx,offset arg2
	call	chkregw
	mov	al,byte ptr [si+opcode.compare]
	or	al,[arg2.areg1]
	stosb
	ret
AOP2	ENDP
;
; one arg, seg goes in b3-4 of opcode
;
AOP3	PROC
	call	noarg2
	call	intsize
	mov	bx,offset arg1
	call	chkseg
	mov	ah,byte ptr [si+OPCODE.COMPARE]
	mov	al,[arg1.areg1]
	cmp	ah,8
	jae	aop3ext
	cmp	al,4
	jae	aop3errx
aop3c:
	shl	al,3
	or	al,ah
	stosb
	ret
aop3ext:
	sub	al,4
	jnc	aop3c
aop3errx:
	stc
	ret
	
AOP3	ENDP
;
; either combo of a reg & rm... bit 1 of opcode set if reg is dest
; bit 0 set if size = word
;
AOP4	PROC
	call	noarg3
	call	intsize
	sub	al,al
	mov	bx,offset arg1
	call	sizeb0
 	cmp	[arg1.mode],AM_REG
	jne	aop4rs
	or	al,2
	mov	bx,offset arg2
	mov	ah,[arg1.areg1]
	jmp	aop4j

aop4rs:
 	cmp	[arg2.mode],AM_REG
	jne	aop4err
	mov	bx,offset arg1
	mov	ah,[arg2.areg1]
aop4j:
	or	al,byte ptr [si+OPCODE.COMPARE]
	stosb
	mov	al,ah
	call	asmrm
	ret
aop4err:
	stc
	ret
AOP4	ENDP
;
; use only rm, bit 0 = size (exception : jmp/call)
;
AOP5	PROC
	call	noarg2
	call	intsize
	mov	bx,offset arg1
	mov	ax,[si+OPCODE.COMPARE]
	test	al,1
	jz	aop5cansize
	cmp	[arg1.asize],DWORDSIZE	; special sizing for jump
	jne	aop5jn4
	and	[PrefixBitmapWord],NOT AS_OPSIZE
	or	ah,8
aop5jn4:
	cmp	[bx+asmop.asize],WORDSIZE
	je	aop5unsized
	cmp	[bx+asmop.asize],NOSIZE
	je	aop5unsized
	stc
	ret
aop5cansize:
	call	sizeb0
aop5unsized:
	stosb
	xchg	al,ah
	and	al,38h
	mov	bx,offset arg1
	call	asmrm2
	ret
AOP5	ENDP
;
; rm,count or rm,cl (shifts) bit 0 = size
; bit 1 set if size = 1, bit 4 set if size = cl, otherwise follow rm with
; a count byte
;
AOP6	PROC
	call	noarg3
	call	intsize
	mov	bx,offset arg1
	mov	ax,[si+opcode.compare]
	call	sizeb0
	cmp	[arg2.mode],AM_REG
	je	aop6cl
	cmp	[arg2.mode],AM_IMM
	je	aop6imm
aop6b:
	stc
	ret
aop6cl:
	cmp	[arg2.asize],BYTESIZE
	jne	aop6b
	cmp	[arg2.areg1],isECX
	jne	aop6b
	or	al,12h
	stosb
	jmp	aop6rm
aop6imm:
	cmp	[arg2.addrx],1
	je	aop6shift1
	stosb
	xchg	al,ah
	call	asmrm2
	mov	al,byte ptr [arg2.addrx]
	stosb
	ret
aop6shift1:
	or	al,10h
	stosb
aop6rm:
	xchg	al,ah
	call	asmrm2
	ret
AOP6	ENDP

⌨️ 快捷键说明

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