;
; GRDP
;
; Copyright(c) LADsoft
;
; David Lindauer, camille@bluegrass.net
;
;
; Regs.asm
;
; Function: Handle register display and input
;
	;MASM MODE
	.model small
	.386


include  eprints.inc 
include  emtrap.inc 
include  einput.inc 
include  edis.inc 
include eoptions.inc
include  ehistory.inc

	PUBLIC	DisplayRegisters, ModifyRegisters, ReadReg
	.code
;
; This is a list corresponding ASCII names for general purpose regs
; with the address the value can be found at;
;

peax	dw	offset RegdumpEAX
	db	13,10,"eax:",0
pebx	dw	offset RegdumpEBX
	db	"ebx:",0
pecx	dw	offset RegdumpECX
	db	"ecx:",0
pedx	dw	offset RegdumpEDX
	db	"edx:",0
pesi	dw	offset RegdumpESI
	db	"esi:",0
pedi	dw	offset RegdumpEDI
	db	"edi:",0
pebp	dw	offset RegdumpEBP
	db	13,10,"ebp:",0
pesp	dw	offset RegdumpESP
	db	"esp:",0
peip	dw	offset RegdumpEIP
	db	"eip:",0
	dw	0
;
; a list of 8-bit register names
;
pal	dw	offset RegdumpEAX
	db	13,10,"al:",0
	dw	offset RegdumpEAX+1
	db	"ah:",0
	dw	offset RegdumpEBX
	db	"bl:",0
	dw	offset RegdumpEBX+1
	db	"bh:",0
	dw	offset RegdumpECX
	db	"cl:",0
	dw	offset RegdumpECX+1
	db	"ch:",0
	dw	offset RegdumpEDX
	db	13,10,"dl:",0
	dw	offset RegdumpEDX+1
	db	"dh:",0
	dw	0
;
; a list of 16-bit register names
;
pax	dw	offset RegdumpEAX
	db	13,10,"ax:",0
	dw	offset RegdumpEBX
	db	"bx:",0
	dw	offset RegdumpECX
	db	"cx:",0
	dw	offset RegdumpEDX
	db	"dx:",0
	dw	offset RegdumpESI
	db	"si:",0
	dw	offset RegdumpEDI
	db	"di:",0
	dw	offset RegdumpEBP
	db	13,10,"bp:",0
	dw	offset RegdumpESP
	db	"sp:",0
	dw	offset RegdumpEIP
	db	"ip:",0
pds	dw	offset RegdumpDS
	db	13,10,"ds: ",0	
PES	dw	offset RegdumpES
	db	"es:",0
pfs	dw	offset RegdumpFS
	db	"fs:",0
pgs	dw	offset RegdumpGS
	db	"gs:",0
Pss	dw	offset RegdumpSS
	db	"ss:",0
pcs	dw	offset RegdumpCS
	db	"cs:",0
	dw	0
peflags	dw	offset RegdumpFLAGS
	db	"eflags:",0
	dw	0
flm	label byte
	db	11
	dd	"NVOV"
	db	10
	dd	"UPDN"
	db	9
	dd	"DIEI"
	db	7
	dd	"PLMI"
	db	6
	dd	"NZZR"
	db	4
	dd	"NAAC"
	db	2
	dd	"POPE"
	db	0
	dd	"NCCY"
	db	-1
	db	0
;
; Print a general purpose reg and it's value
;
rPutDword	PROC	
	test	[optdword],0ffh
	jz	rPutWord
	lods	word ptr cs:[si]; Get pointer to val
	mov	bx,ax
	mov	eax,[bx]	; Get val
	push	eax		;
	mov	bx,si		; Get text pointer
	call	olMessage
	pop	eax		;
	call	printdword	; Print value
	call	printspace	;
	ret
rPutDword	ENDP	
;
; Print a segment reg and its value
;
rPutWord	PROC	
	lods	word ptr cs:[si]; Get pointer to value
	mov	bx,ax
	mov	ax,[bx]		; Get value
	push	ax		;
	mov	bx,si		; Pointer to text
	call	olMessage
	pop	ax		;
	call	printword	; Print value
	call	printspace	;
	ret
rPutWord	ENDP	
;
; Print either the GP regs or the SEG regs
; INPUT: DX has the address of the appropriate print routine
;	SI points to text
; By implication, two consecutive bytes of 0 exit the routine, else we
; print each string until we reach that 00 00
;

PrintaFew	PROC	
	call	dx		; Call the print routine
pf_lp:
	lods	byte ptr cs:[si]; Wade past the text
	or	al,al		;
	jnz	pf_lp		;
	test	WORD PTR cs:[si],-1 ; See if trailer found
	jnz	PrintAFew	; Go print another
	ret
PrintAFew	ENDP	
;
; try to find a match for a register spec
; INPUT: SI points at the input line where we might find a register by name
;	DI points to an EAX structure consisting of a pointer to a bucket
;		to put EAX into, followed by a display string of 'EAX'
; OUTPUT:SI is moved past the register if we found one, else same
;	DI points to bucket to hold this register value if register found
;
skimreg PROC
	push	di			;save address of structure
	push	si			;save address of input
	xchg	si,di			;di now input, si is structure
	add	si,2			;go past EAX bucket pointer to str
srlp:
	cmp	byte ptr cs:[si],' '	;anything below a space
	jnc	oktry			;is OK, so skip 0D, 0A at EAX
	inc	si			;goto next character
	jmp	srlp			;until letter is found
oktry:
	cmp	byte ptr cs:[si],':'	;colon follows all register names
	jz	match			;so if all alike, we found our reg
	cmps	byte ptr cs:[si],es:[di] ;else do a character match
	jz	oktry			;if a match, keep going to colon
	pop	di			;else pop address of input to di
	add	sp,2			;clear struct address off stack
srlp2:
	lods	byte ptr cs:[si]	;find terminating 0, following colon
	or	al,al			;is this it?
	jnz	srlp2			;keep looking until found
	test 	word ptr cs:[si],0ffffh	;table ends with word of 0
	xchg	si,di			;get our regs straightened out
	jnz	skimreg			;and examine next struct
	sub	al,al			;no find, so
	inc	al			;return no carry
	ret
match:
	add	sp,2			;clear input address off stack
	sub	eax,eax			;clear out EAX
	xchg	si,di			;SI now input past found register
	pop	di			;di points to top struct
	mov	di,cs:[di]		;point to his bucket
	stc				;indicate register found
	ret
skimreg ENDP
;
; search all the name tables for a match
; INPUT: SI points at the input line where we expect to find a register
; OUTPUT: ZR if found a non-segment register, NZ if we didn't
;	CY if the request was NOT for a segment register, NC if it was
;	SI moved past the register on the input line
;
FindRegister	PROC
	mov	di,offset cs:peax	;find pointer to EAX bucket
	call	skimreg			;look for register string match
	mov	cl,4			;used for dword length
	jc	frnoseg			;carry means we found dword reg
	mov	di,offset cs:pal	;else look for byte reg
	call	skimreg			;save technique
	mov	cl,1			;set byte length
	jc	frnoseg			;in case we found it
	mov	di,offset cs:peflags	;else maybe user doing flags?
	call	skimreg			;try 'eflags'
	mov	cl,4			;say 4 bytes for this
	jc	frnoseg			;if found
	mov	bl,[si+1]		;else bl=2d char in input string
	mov	di,offset cs:pax	;look for word regs
	call	skimreg			;in the table
	mov	cl,2			;assume word
	jnc	frnotfound		;if not found, bl is ???
	cmp	bl,'s'			;might it be a segment reg?
	stc				;assume not???
	jnz	frnoseg			;jmp if not
	clc				;else clear carry
frnoseg:
	mov	al,0ffH			;set ZF without affecting carry flag
	inc	al
	ret				;and return success
frnotfound:
	sub	ax,ax			;set NZ
	inc	ax
	stc				;and the carry
	ret
FindRegister	ENDP
;
; read the value of a reg (used by input routines)
; INPUT: SI points at the input line 
; OUTPUT:If we found a byte or word register, EAX holds the zero-extended
;	value that was in the corresponding bucket.
;	If we found a dword register, EAX holds the dword value
;	NZ if register not found by name, but still might be a number
;		Else, NC if segment reg, CY if non-segment reg found
;	SI moved past a register found by name, else not moved
;
ReadReg		PROC
	push	ecx			;ECX holds ???
	call	FindRegister		;see if we found a non-segment reg
	jnz	notreg			;if not, jmp
	pushf				;save flags (carry?)
	mov	eax,[di]		;get value from bucket
	cmp	cl,4			;was it a dword?
	jz	rr_exit			;if so, exit
	movzx	eax,ax			;else zero extend into EAX
	cmp	cl,2			;was it a word register
	jz	rr_exit			;if so, we have it
	movzx	eax,al			;else zero extend EAX
rr_exit:
	popf				;restore flags
notreg:
	pop	ecx			;and ECX
	ret
ReadReg	ENDP
;
; Read value for a register back into memory (R) command
;
ReadRegValue	PROC
	call	WadeSpace
	jz	doregprompt
	inc	si
	cmp	al,':'
	jz	ReadRegValue
	cmp	al,'='
	jz	ReadRegValue
	dec	si
	call	ReadNumber
	ret
doregprompt:
	push	bx			; Else put up prompt
	push	cx			;
	PRINT_MESSAGE	<13,10,": ">
	call	histoff
	call	GetInputLine		; Get input line
	call	histon
	pop	cx			;
	pop	bx			;
	call	WadeSpace		; Ignore spaces
	jz	short rr_out		; Quit if so
	call	ReadNumber
	ret
rr_out:
	stc
	ret
ReadRegValue	ENDP	
;
; main 'Reg' command
;
ModifyRegisters	PROC	
	call	wadespace		; Wade through spaces
	jz	DisplayRegisters	; Display regs
	call	FindRegister
	jnz	badreg
	push	di
	call	ReadRegValue
	pop	di
	jc	badreg2
	cmp	cl,4
	jnz	wordreg
	mov	[di],eax
	clc
	ret
wordreg:
	cmp	cl,2
	jnz	bytereg
	mov	[di],ax
badreg2:
	clc
	ret
badreg:
	stc
	ret
bytereg:
	mov	[di],al
	ret
ModifyRegisters ENDP
putflags PROC
	mov	si,offset cs:flm
putflags2:
	lods	byte ptr cs:[si]
	or	al,al
	js	pfdone
	movzx	ax,al
	bt	word ptr [RegdumpFLAGS],ax
	lods	dword ptr cs:[si]
	mov	edx,eax
	jc	isclr
	shr	edx,16
isclr:
	xchg	dh,dl
	call	PutChar
	xchg	dl,dh
	call	PutChar
	call	PrintSpace
	jmp	putflags2
pfdone:
	ret
putflags ENDP
;
; Display the processor regs
;
DisplayRegisters	PROC	
	mov	word ptr [RegdumpEIP+2],0	;clear high word of EIP 
	pushfd					;move eflags
	pop	eax				;to EAX
	shr	eax,16				;get upper 16 flagbits
	mov	word ptr [RegdumpFLAGS+2],ax	;save in high flag bucket
	mov	si, offset cs:peax		; Print GP regs
	mov	dx,offset cs:rPutDword		; with the DWORD function
	call	PrintAFew			; Print them
	mov	si,offset cs:peflags		;Put the flags
	call    rPutDword		
	call	putflags
	mov	si,offset cs:pds		; Now put the segs
	mov	dx,offset cs:rPutWord	
	call	PrintAFew		
	mov	bx,word ptr [RegdumpEIP]	; Dissassemble at current code pointer
	mov	dx,[RegdumpCS]		
	call	DisOneLine		
	clc
	ret
DisplayRegisters	ENDP	
END