format binary
use32
	db	'MENUET01'
	dd	1
	dd	start
	dd	i_end
	dd	used_mem
	dd	used_mem
	dd	i_param
	dd	0

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; GUI ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

data_width equ 80
data_x_pos equ 12
data_x_size equ data_width*6

title_x_pos equ 30
title_y_pos equ 32
title_y_size equ 10

registers_x_pos equ data_x_pos
registers_y_pos equ (title_y_pos + title_y_size)
registers_y_size equ 30

dump_y_pos equ (registers_y_pos + registers_y_size + 5)
dump_height equ 4
dump_y_size equ (dump_height*10)

disasm_y_pos equ (dump_y_pos + dump_y_size + 4)
disasm_height equ 16
disasm_y_size equ (disasm_height*10)

messages_width equ data_width
messages_height equ 12
messages_x_pos equ data_x_pos
messages_y_pos equ (disasm_y_pos + disasm_y_size + 4)
messages_x_size equ messages_width*6
messages_y_size equ messages_height*10

cmdline_width equ data_width
cmdline_x_pos equ data_x_pos
cmdline_y_pos equ (messages_y_pos + messages_y_size + 10)
cmdline_x_size equ messages_x_size
cmdline_y_size equ 10

wnd_x_size equ (data_x_pos + messages_x_size + data_x_pos)
wnd_y_size equ (cmdline_y_pos + cmdline_y_size + data_x_pos)

start:
	mov	edi, messages
	mov	ecx, messages_width*messages_height
	mov	al, ' '
	rep	stosb
	xor	eax, eax
	mov	[messages_pos], eax
	mov	[cmdline_len], eax
	mov	[cmdline_pos], eax
	mov	edi, needzerostart
	mov	ecx, (needzeroend-needzerostart+3)/4
	rep	stosd
	mov	esi, begin_str
	call	put_message_nodraw
; set event mask - default events and debugging events
	push	40
	pop	eax
	mov	ebx, 0x107
	int	40h
; set debug messages buffer
	mov	ecx, dbgbufsize
	mov	dword [ecx], 256
	xor	ebx, ebx
	mov	[ecx+4], ebx
	mov	al, 69
	int	40h
	mov	esi, i_param
	call	skip_spaces
	test	al, al
	jz	dodraw
	push	esi
	call	draw_window
	pop	esi
	call	OnLoadInit
	jmp	waitevent
dodraw:
	call	draw_window
waitevent:
	push	10
	pop	eax
	int	40h
	cmp	al, 9
	jz	debugmsg
	dec	eax
	jz	dodraw
	dec	eax
	jz	keypressed
	dec	eax
	jnz	waitevent
; button pressed - we have only one button (close)
	push	-1
	pop	eax
	int	40h
keypressed:
	mov	al, 2
	int	40h
	shr	eax, 8
	cmp	al, 8
	jz	.backspace
	cmp	al, 0xB0
	jz	.left
	cmp	al, 0xB3
	jz	.right
	cmp	al, 0x0D
	jz	.enter
	cmp	al, 0xB6
	jz	.del
	cmp	al, 0xB4
	jz	.home
	cmp	al, 0xB5
	jz	.end
	cmp	al, 0xB1
	jz	.down
	cmp	al, 0xB2
	jz	.up
	cmp	al, 0xD8
	jz	CtrlF7
	cmp	al, 0xD9
	jz	CtrlF8
	cmp	[cmdline_len], cmdline_width
	jae	waitevent
	push	eax
	call	clear_cmdline_end
	pop	eax
	mov	edi, cmdline
	mov	ecx, [cmdline_len]
	add	edi, ecx
	lea	esi, [edi-1]
	sub	ecx, [cmdline_pos]
	std
	rep	movsb
	cld
	stosb
	inc	[cmdline_len]
	call	draw_cmdline_end
	inc	[cmdline_pos]
	call	draw_cursor
	jmp	waitevent
.backspace:
	cmp	[cmdline_pos], 0
	jz	waitevent
	dec	[cmdline_pos]
.delchar:
	call	clear_cmdline_end
	mov	edi, [cmdline_pos]
	dec	[cmdline_len]
	mov	ecx, [cmdline_len]
	sub	ecx, edi
	add	edi, cmdline
	lea	esi, [edi+1]
	rep	movsb
	call	draw_cmdline_end
	call	draw_cursor
	jmp	waitevent
.del:
	mov	eax, [cmdline_pos]
	cmp	eax, [cmdline_len]
	jae	waitevent
	jmp	.delchar
.left:
	cmp	[cmdline_pos], 0
	jz	waitevent
	call	hide_cursor
	dec	[cmdline_pos]
	call	draw_cursor
	jmp	waitevent
.right:
	mov	eax, [cmdline_pos]
	cmp	eax, [cmdline_len]
	jae	waitevent
	call	hide_cursor
	inc	[cmdline_pos]
	call	draw_cursor
	jmp	waitevent
.home:
	call	hide_cursor
	and	[cmdline_pos], 0
	call	draw_cursor
	jmp	waitevent
.end:
	call	hide_cursor
	mov	eax, [cmdline_len]
	mov	[cmdline_pos], eax
	call	draw_cursor
.up:
.down:
	jmp	waitevent
.enter:
	mov	ecx, [cmdline_len]
	test	ecx, ecx
	jz	waitevent
	mov	esi, cmdline
	mov	byte [esi+ecx], 0
	and	[cmdline_pos], 0
	push	esi
	call	clear_cmdline_end
	call	draw_cursor
	pop	esi
	and	[cmdline_len], 0
; skip leading spaces
	call	skip_spaces
	cmp	al, 0
	jz	waitevent
; now esi points to command
	push	esi
	mov	esi, prompt
	call	put_message_nodraw
	pop	esi
	push	esi
	call	put_message_nodraw
z1:	mov	esi, newline
	call	put_message
	pop	esi
	push	esi
	call	get_arg
	mov	[curarg], esi
	pop	edi
	mov	esi, commands
	call	find_cmd
	mov	eax, aUnknownCommand
	jc	.x11
; check command requirements
; flags field:
; &1: command may be called without parameters
; &2: command may be called with parameters
; &4: command may be called without loaded program
; &8: command may be called with loaded program
	mov	eax, [esi+8]
	mov	ecx, [curarg]
	cmp	byte [ecx], 0
	jz	.noargs
	test	byte [esi+16], 2
	jz	.x11
	jmp	@f
.noargs:
	test	byte [esi+16], 1
	jz	.x11
@@:
	cmp	[debuggee_pid], 0
	jz	.nodebuggee
	mov	eax, aAlreadyLoaded
	test	byte [esi+16], 8
	jz	.x11
	jmp	.x9
.nodebuggee:
	mov	eax, need_debuggee
	test	byte [esi+16], 4
	jnz	.x9
.x11:
	xchg	esi, eax
	call	put_message
.x10:
	jmp	waitevent
.x9:
	call	dword [esi+4]
	jmp	.x10

find_cmd:
; all commands are case-insensitive
	push	edi
.x4:
	mov	al, [edi]
	cmp	al, 0
	jz	.x5
	cmp	al, 'A'
	jb	@f
	cmp	al, 'Z'
	ja	@f
	or	al, 20h
@@:
	stosb
	jmp	.x4
.x5:
; find command
	pop	edi
.x6:
	cmp	dword [esi], 0
	jz	.x7
	push	esi
	mov	esi, [esi]
	lodsb
	movzx	ecx, al
	push	edi
	repz	cmpsb
	pop	edi
	pop	esi
	jz	.x8
	add	esi, 17
	jmp	.x6
.x7:
	stc
.x8:
	ret

get_arg:
	lodsb
	cmp	al, ' '
	ja	get_arg
	mov	byte [esi-1], 0
	cmp	al, 0
	jnz	skip_spaces
	dec	esi
skip_spaces:
	lodsb
	cmp	al, 0
	jz	@f
	cmp	al, ' '
	jbe	skip_spaces
@@:	dec	esi
	ret

clear_cmdline_end:
	mov	ebx, [cmdline_pos]
	mov	ecx, [cmdline_len]
	sub	ecx, ebx
	push	13
	pop	eax
	imul	ebx, 6
	imul	ecx, 6
	inc	ecx
	add	ebx, cmdline_x_pos
	shl	ebx, 16
	or	ebx, ecx
	mov	ecx, cmdline_y_pos*10000h + cmdline_y_size
	mov	edx, 0xFFFFFF
	int	40h
	ret

draw_cmdline:
	xor	ebx, ebx
	jmp	@f
draw_cmdline_end:
	mov	ebx, [cmdline_pos]
@@:
	mov	esi, [cmdline_len]
	sub	esi, ebx
	push	4
	pop	eax
	xor	ecx, ecx
	lea	edx, [cmdline+ebx]
	imul	ebx, 6
	add	ebx, cmdline_x_pos
	shl	ebx, 16
	or	ebx, cmdline_y_pos+1
	int	40h
	ret

put_message_nodraw:
; in: esi->ASCIZ message
	mov	edx, [messages_pos]
.m:
	lea	edi, [messages+edx]
.l:
	lodsb
	cmp	al, 0
	jz	.done
	call	test_scroll
	cmp	al, 10
	jz	.newline
	cmp	al, '%'
	jnz	@f
	cmp	dword [esp], z1
	jnz	.format
@@:
	stosb
	inc	edx
	jmp	.l
.newline:
	push	edx
	mov	ecx, messages_width
	xor	eax, eax
	xchg	eax, edx
	div	ecx
	xchg	eax, edx
	pop	edx
	test	eax, eax
	jz	.m
	sub	edx, eax
	add	edx, ecx
	jmp	.m
.done:
	mov	[messages_pos], edx
	ret
.format:
; at moment all format specs must be %<digit>X
	lodsb	; get <digit>
	sub	al, '0'
	movzx	ecx, al
	lodsb
	pop	eax
	pop	ebp
	push	eax
; write number in ebp with ecx digits
	dec	ecx
	shl	ecx, 2
.writenibble:
	push	ecx
	call	test_scroll
	pop	ecx
	mov	eax, ebp
	shr	eax, cl
	and	al, 0xF
	cmp	al, 10
	sbb	al, 69h
	das
	stosb
	inc	edx
	sub	ecx, 4
	jns	.writenibble
	jmp	.l

test_scroll:
	cmp	edx, messages_width*messages_height
	jnz	.ret
	push	esi
	mov	edi, messages
	lea	esi, [edi+messages_width]
	mov	ecx, (messages_height-1)*messages_width/4
	rep	movsd
	push	eax
	mov	al, ' '
	push	edi
	push	messages_width
	pop	ecx
	sub	edx, ecx
	rep	stosb
	pop	edi
	pop	eax
	pop	esi
.ret:	ret

put_message:
	call	put_message_nodraw

draw_messages:
	push	13
	pop	eax
	mov	edx, 0xFFFFFF
	mov	ebx, messages_x_pos*10000h+messages_x_size
	mov	ecx, messages_y_pos*10000h+messages_y_size
	int	40h
	mov	edx, messages
	push	messages_width
	pop	esi
	xor	ecx, ecx
	mov	al, 4
	mov	ebx, messages_x_pos*10000h+messages_y_pos
@@:
	int	40h
	add	edx, esi
	add	ebx, 10
	cmp	edx, messages+messages_width*messages_height
	jb	@b
	ret

draw_cursor:
	push	38
	pop	eax
	mov	ecx, cmdline_y_pos*10001h+cmdline_y_size-1
	mov	ebx, [cmdline_pos]
	imul	ebx, 6
	add	ebx, cmdline_x_pos
	mov	edx, ebx
	shl	ebx, 16
	or	ebx, edx
	xor	edx, edx
	int	40h
	ret
hide_cursor:
	mov	ebx, [cmdline_pos]
	push	13
	pop	eax
	imul	ebx, 6
	add	ebx, cmdline_x_pos
	shl	ebx, 16
	inc	ebx
	mov	ecx, cmdline_y_pos*10000h + cmdline_y_size
	mov	edx, 0xFFFFFF
	int	40h
	mov	ebx, [cmdline_pos]
	cmp	ebx, [cmdline_len]
	jae	.ret
	mov	al, 4
	xor	ecx, ecx
	lea	edx, [cmdline+ebx]
	imul	ebx, 6
	add	ebx, cmdline_x_pos
	shl	ebx, 16
	or	ebx, cmdline_y_pos+1
	push	1
	pop	esi
	int	40h
.ret:
	ret

redraw_title:
	push	13
	pop	eax
	mov	edx, 0xFFFFFF
	mov	ebx, title_x_pos*10000h + data_x_pos+data_x_size-title_x_pos
	mov	ecx, title_y_pos*10000h + title_y_size
	int	40h
draw_title:
	mov	al, 38
	mov	ebx, (data_x_pos-2)*10000h + title_x_pos-5
	mov	ecx, (title_y_pos+5)*10001h
	xor	edx, edx
	int	40h
	push	NoPrgLoaded_len
	pop	esi
	cmp	[debuggee_pid], 0
	jz	@f
	mov	esi, [prgname_len]
@@:	imul	ebx, esi, 6
	add	ebx, title_x_pos+4
	shl	ebx, 16
	mov	bx, data_x_pos+data_x_size-10-5-6*7
	cmp	[bSuspended], 0
	jz	@f
	add	ebx, 6
@@:
	int	40h
	mov	ebx, (data_x_pos+data_x_size-10+4)*0x10000 + data_x_pos+data_x_size+2
	int	40h
	mov	al, 4
	mov	ebx, title_x_pos*10000h+title_y_pos
	xor	ecx, ecx
	mov	edx, NoPrgLoaded_str
	cmp	[debuggee_pid], 0
	jz	@f
	mov	edx, [prgname_ptr]
@@:
	int	40h
	cmp	[debuggee_pid], 0
	jz	.nodebuggee
	mov	ebx, (data_x_pos+data_x_size-10-6*7)*10000h + title_y_pos
	mov	edx, aRunning
	push	7
	pop	esi
	cmp	[bSuspended], 0
	jz	@f
	add	ebx, 6*10000h
	mov	edx, aPaused
	dec	esi
@@:
	int	40h
	ret
.nodebuggee:
	mov	al, 38
	mov	ebx, (data_x_pos+data_x_size-10-6*7-5)*0x10000 + data_x_pos+data_x_size+2
	mov	ecx, (title_y_pos+5)*10001h
	xor	edx, edx
	jmp	@b

draw_register:
; in: esi->value, edx->string, ecx=string len, ebx=coord
	push	edx
	push	ecx
	push	esi
	mov	eax, esi
	mov	esi, ecx
; color
	mov	ecx, 808080h
	cmp	[debuggee_pid], 0
	jz	.cd
	cmp	[bSuspended], 0
	jz	.cd
	xor	ecx, ecx
	mov	edi, [eax]
	cmp	dword [eax+oldcontext-context], edi
	jz	.cd
	mov	ecx, 0x00AA00
.cd:
	push	4
	pop	eax
	int	40h
	imul	esi, 60000h
	lea	edx, [ebx+esi]
	mov	al, 47
	mov	ebx, 80101h
	mov	esi, ecx
	pop	ecx
	int	40h
	lea	ebx, [edx+60000h*18]
	mov	esi, ecx
	pop	ecx
	pop	edx
	add	edx, ecx
	ret
draw_flag:
	movzx	edi, byte [edx+7]
	bt	[_eflags], edi
	jc	.on
	or	byte [edx], 20h
	jmp	.onoff
.on:
	and	byte [edx], not 20h
.onoff:
	mov	ecx, 808080h
	cmp	[debuggee_pid], 0
	jz	.doit
	cmp	[bSuspended], 0
	jz	.doit
	xor	ecx, ecx
	bt	[_eflags], edi
	lahf
	bt	dword [_eflags + oldcontext - context], edi
	rcl	ah, 1
	test	ah, 3
	jp	.doit
	mov	ecx, 0x00AA00
.doit:
	mov	ah, 0
	int	40h
	ret

redraw_registers:
	push	13
	pop	eax
	mov	edx, 0xFFFFFF
	mov	ebx, data_x_pos*10000h + data_x_size
	mov	ecx, registers_y_pos*10000h + registers_y_size
	int	40h
draw_registers:
	mov	esi, _eax
	push	4
	pop	ecx
	mov	edx, regs_strs
	mov	ebx, registers_x_pos*10000h+registers_y_pos
	call	draw_register
	add	esi, _ebx-_eax
	call	draw_register
	add	esi, _ecx-_ebx
	call	draw_register
	add	esi, _edx-_ecx
	call	draw_register
	mov	ebx, registers_x_pos*10000h+registers_y_pos+10
	add	esi, _esi-_edx
	call	draw_register
	add	esi, _edi-_esi
	call	draw_register
	add	esi, _ebp-_edi
	call	draw_register
	add	esi, _esp-_ebp
	call	draw_register
	mov	ebx, registers_x_pos*10000h+registers_y_pos+20
	add	esi, _eip-_esp
	call	draw_register
	mov	cl, 7
	add	esi, _eflags-_eip
	call	draw_register
	mov	al, 4
	mov	ecx, 808080h
	cmp	[debuggee_pid], 0
	jz	@f
	cmp	[bSuspended], 0
	jz	@f
	xor	ecx, ecx
@@:
	mov	edx, aColon
	xor	esi, esi
	inc	esi
	mov	ebx, (registers_x_pos+37*6)*10000h + registers_y_pos+20
	int	40h
	mov	edx, flags
@@:
	add	ebx, 2*6*10000h
	call	draw_flag
	inc	edx
	cmp	dl, flags_bits and 0xFF
	jnz	@b
	ret

redraw_dump:
	push	13
	pop	eax
	mov	edx, 0xFFFFFF
	mov	ebx, data_x_pos*10000h + data_x_size
	mov	ecx, dump_y_pos*10000h + dump_y_size
	int	40h
draw_dump:
; addresses
	mov	al, 47
	mov	ebx, 80100h
	mov	edx, data_x_pos*10000h + dump_y_pos
	mov	ecx, [dumppos]
	mov	esi, 808080h
	cmp	[debuggee_pid], 0
	jz	@f
	cmp	[bSuspended], 0
	jz	@f
	xor	esi, esi
@@:
	int	40h
	add	ecx, 10h
	add	edx, 10
	cmp	dl, dump_y_pos + dump_y_size
	jb	@b
; hex dump of data
	mov	ebx, 20101h
	mov	ecx, dumpdata
	push	ecx
	xor	edi, edi
	mov	edx, (data_x_pos+12*6)*10000h + dump_y_pos
	cmp	[dumpread], edi
	jz	.hexdumpdone1
.hexdumploop1:
	int	40h
	add	edx, 3*6*10000h
	inc	ecx
	inc	edi
	test	edi, 15
	jz	.16
	test	edi, 7
	jnz	@f
	add	edx, 2*6*10000h - 10 + 6*(3*10h+2)*10000h
.16:
	add	edx, 10 - 6*(3*10h+2)*10000h
@@:
	cmp	edi, [dumpread]
	jb	.hexdumploop1
.hexdumpdone1:
	mov	al, 4
	mov	ecx, esi
	mov	ebx, edx
	push	2
	pop	esi
	mov	edx, aQuests
.hexdumploop2:
	cmp	edi, dump_height*10h
	jae	.hexdumpdone2
	int	40h
	add	ebx, 3*6*10000h
	inc	edi
	test	edi, 15
	jz	.16x
	test	edi, 7
	jnz	.hexdumploop2
	add	ebx, 2*6*10000h - 10 + 6*(3*10h+2)*10000h
.16x:
	add	ebx, 10 - 6*(3*10h+2)*10000h
	jmp	.hexdumploop2
.hexdumpdone2:
	dec	esi
; colon, minus signs
	mov	ebx, (data_x_pos+8*6)*10000h + dump_y_pos
	mov	edx, aColon
@@:
	int	40h
	add	ebx, 10
	cmp	bl, dump_y_pos+dump_height*10
	jb	@b
	mov	ebx, (data_x_pos+(12+3*8)*6)*10000h + dump_y_pos
	mov	edx, aMinus
@@:
	int	40h
	add	ebx, 10
	cmp	bl, dump_y_pos+dump_height*10
	jb	@b
; ASCII data
	mov	ebx, (data_x_pos+(12+3*10h+2+2)*6)*10000h + dump_y_pos
	mov	edi, dump_height*10h
	pop	edx
.asciiloop:
	push	edx
	cmp	byte [edx], 20h
	jae	@f
	mov	edx, aPoint
@@:
	int	40h
	pop	edx
	inc	edx
	add	ebx, 6*10000h
	dec	edi
	jz	.asciidone
	test	edi, 15
	jnz	.asciiloop
	add	ebx, 10 - 6*10h*10000h
	jmp	.asciiloop
.asciidone:
	ret

redraw_disasm:
	push	13
	pop	eax
	mov	edx, 0xFFFFFF
	mov	ebx, data_x_pos*10000h + data_x_size
	mov	ecx, (disasm_y_pos-1)*10000h + (disasm_y_size+1)
	int	40h
draw_disasm:
	mov	eax, [disasm_start_pos]
	mov	[disasm_cur_pos], eax
	and	[disasm_cur_str], 0
.loop:
	push	[disasm_cur_pos]
	call	disasm_instr
	pop	ebp
	jc	.loopend
	xor	esi, esi	; default color: black
	mov	ebx, data_x_pos*10000h + data_x_size
	mov	ecx, [disasm_cur_str]
	imul	ecx, 10*10000h
	add	ecx, (disasm_y_pos-1)*10000h + 10
	mov	eax, ebp
	pushad
	call	find_enabled_breakpoint
	popad
	jnz	.nored
	push	13
	pop	eax
	mov	edx, 0xFF0000
	int	40h
.nored:
	mov	eax, [_eip]
	cmp	eax, ebp
	jnz	.noblue
	push	13
	pop	eax
	mov	edx, 0x0000FF
	int	40h
	mov	esi, 0xFFFFFF	; on blue bgr, use white color
.noblue:
	push	47
	pop	eax
	mov	ebx, 80100h
	mov	edx, [disasm_cur_str]
	imul	edx, 10
	add	edx, data_x_pos*10000h + disasm_y_pos
	mov	ecx, ebp
	int	40h
	mov	al, 4
	lea	ebx, [edx+8*6*10000h]
	mov	ecx, esi
	push	1
	pop	esi
	mov	edx, aColon
	int	40h
	push	9
	pop	edi
	lea	edx, [ebx+2*6*10000h]
	mov	esi, ecx
	mov	al, 47
	mov	ebx, 20101h
	mov	ecx, ebp
	sub	ecx, [disasm_start_pos]
	add	ecx, disasm_buffer
.drawhex:
	int	40h
	add	edx, 6*3*10000h
	inc	ecx
	inc	ebp
	cmp	ebp, [disasm_cur_pos]
	jae	.hexdone
	dec	edi
	jnz	.drawhex
	push	esi
	mov	esi, [disasm_cur_pos]
	dec	esi
	cmp	esi, ebp
	pop	esi
	jbe	.drawhex
	mov	al, 4
	lea	ebx, [edx-6*10000h]
	mov	ecx, esi
	push	3
	pop	esi
	mov	edx, aDots
	int	40h
	mov	esi, ecx
.hexdone:
	xor	eax, eax
	mov	edi, disasm_string
	mov	edx, edi
	or	ecx, -1
	repnz	scasb
	not	ecx
	dec	ecx
	xchg	ecx, esi
	mov	ebx, [disasm_cur_str]
	imul	ebx, 10
	add	ebx, (data_x_pos+6*40)*10000h+disasm_y_pos
	mov	al, 4
	int	40h
	inc	[disasm_cur_str]
	cmp	[disasm_cur_str], disasm_height
	jb	.loop
.loopend:
	ret

update_disasm_eip:
; test if instruction at eip is showed
	mov	ecx, disasm_height
	mov	eax, [disasm_start_pos]
	mov	[disasm_cur_pos], eax
@@:
	mov	eax, [_eip]
	cmp	[disasm_cur_pos], eax
	jz	redraw_disasm
	push	ecx
	call	disasm_instr
	pop	ecx
	jc	@f
	loop	@b
@@:
update_disasm_eip_force:
	mov	eax, [_eip]
	mov	[disasm_start_pos], eax
update_disasm:
	cmp	[debuggee_pid], 0
	jz	.no
	push	69
	pop	eax
	push	6
	pop	ebx
	mov	ecx, [debuggee_pid]
	mov	edi, disasm_buffer
	mov	edx, 256
	mov	esi, [disasm_start_pos]
	int	40h
	cmp	eax, -1
	jnz	@f
	mov	esi, read_mem_err
	call	put_message
.no:
	xor	eax, eax
@@:
	mov	[disasm_buf_size], eax
	call	restore_from_breaks
	jmp	redraw_disasm

draw_window:
; start redraw
	push	12
	pop	eax
	push	1
	pop	ebx
	int	40h
; define window
	xor	eax, eax
	mov	ebx, wnd_x_size
	mov	ecx, wnd_y_size
	mov	edx, 3FFFFFFh
	int	40h
; caption
	mov	al, 4
	mov	ecx, 0xFFFFFF
	mov	ebx, 80008h
	mov	edx, caption_str
	push	caption_len
	pop	esi
	int	40h
; messages frame
	mov	al, 38
	mov	ebx, (messages_x_pos-2)*10000h + (messages_x_pos+messages_x_size+2)
	push	ebx
	mov	ecx, (messages_y_pos-2)*10001h
	xor	edx, edx
	int	40h
	mov	ecx, (messages_y_pos+messages_y_size+2)*10001h
	int	40h
	mov	ebx, (messages_x_pos-2)*10001h
	push	ebx
	mov	ecx, (messages_y_pos-2)*10000h + (messages_y_pos+messages_y_size+2)
	int	40h
	mov	ebx, (messages_x_pos+messages_x_size+2)*10001h
	push	ebx
	int	40h
; command line frame
	mov	ecx, (cmdline_y_pos-2)*10000h + (cmdline_y_pos+cmdline_y_size+2)
	pop	ebx
	int	40h
	pop	ebx
	int	40h
	pop	ebx
	mov	ecx, (cmdline_y_pos+cmdline_y_size+2)*10001h
	int	40h
	mov	ecx, (cmdline_y_pos-2)*10001h
	int	40h
; messages
	call	draw_messages
; command line & cursor
	call	draw_cmdline
	call	draw_cursor
; title & registers & dump & disasm
	mov	al, 38
	mov	ebx, (data_x_pos-2)*10001h
	mov	ecx, (title_y_pos+5)*10000h + (messages_y_pos-2)
	int	40h
	mov	ebx, (data_x_pos+data_x_size+2)*10001h
	int	40h
	mov	ebx, (data_x_pos-2)*10000h + (data_x_pos+data_x_size+2)
	mov	ecx, (dump_y_pos-3)*10001h
	int	40h
	mov	ecx, (disasm_y_pos-4)*10001h
	int	40h
	call	draw_title
	call	draw_registers
	call	draw_dump
	call	draw_disasm
; end redraw
	mov	al, 12
	push	2
	pop	ebx
	int	40h
	ret

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; DEBUGGING ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

OnHelp:
	mov	esi, help_msg
	mov	edi, [curarg]
	cmp	byte [edi], 0
	jz	.x
	mov	esi, help_groups
	call	find_cmd
	jc	.nocmd
	mov	esi, [esi+12]
.x:
	jmp	put_message
.nocmd:
	mov	esi, aUnknownCommand
	jmp	.x

OnQuit:
	xor	eax, eax
	dec	eax
	int	40h

get_new_context:
	mov	esi, context
	mov	edi, oldcontext
	mov	ecx, 10
	rep	movsd
get_context:
	push	1
	pop	ebx
	push	69
	pop	eax
	mov	ecx, [debuggee_pid]
	mov	esi, context
	push	28h
	pop	edx
	int	40h
	ret
set_context:
	push	2
	pop	ebx
	push	69
	pop	eax
	mov	ecx, [debuggee_pid]
	mov	esi, context
	push	28h
	pop	edx
	int	40h
	ret

get_dump:
	mov	edi, dumpdata
	mov	esi, [edi-4]
	mov	edx, dump_height*10h
	mov	ecx, edx
	xor	eax, eax
	push	edi
	rep	stosb
	pop	edi
	mov	ecx, [debuggee_pid]
	mov	al, 69
	push	6
	pop	ebx
	int	40h
	cmp	eax, -1
	jnz	@f
	mov	esi, read_mem_err
	call	put_message
	xor	eax, eax
@@:
	mov	[edi-8], eax
;	call	restore_from_breaks
;	ret
restore_from_breaks:
; in: edi=buffer,eax=size,esi=address
	mov	ebx, breakpoints
@@:
	test	byte [ebx+4], 1
	jz	.cont		; ignore invalid
	test	byte [ebx+4], 2 or 8
	jnz	.cont		; ignore disabled and memory breaks
	mov	ecx, [ebx]
	sub	ecx, esi
	cmp	ecx, eax
	jae	.cont
	mov	dl, [ebx+5]
	mov	[edi+ecx], dl
.cont:
	add	ebx, 6
	cmp	ebx, breakpoints+breakpoints_n*6
	jb	@b
	ret

OnLoad:
	mov	esi, [curarg]
OnLoadInit:
	mov	edi, loadname
	or	[prgname_len], -1
	mov	[prgname_ptr], edi
.copyname:
	lodsb
	stosb
	inc	[prgname_len]
	cmp	al, '/'
	jnz	@f
	or	[prgname_len], -1
	mov	[prgname_ptr], edi
@@:
	cmp	al, ' '
	ja	.copyname
	mov	byte [edi-1], 0
	and	[load_params], 0
	dec	esi
	call	skip_spaces
	cmp	al, 0
	jz	@f
	mov	[load_params], esi
@@:
	and	[dumppos], 0
do_reload:
	push	18
	pop	eax
	push	7
	pop	ebx
	int	40h
	mov	[dbgwnd], eax
	xchg	ecx, eax
	push	70
	pop	eax
	mov	ebx, fn70_load_block
	int	40h
	test	eax, eax
	jns	.load_ok
.load_err:
	push	eax
	mov	esi, load_err_msg
	call	put_message
	pop	eax
	not	eax
	cmp	eax, 0x20
	jae	.unk_err
	mov	esi, [load_err_msgs+eax*4]
	test	esi, esi
	jnz	put_message
.unk_err:
	mov	esi, unk_err_msg
	inc	eax
	push	eax
	call	put_message_nodraw
	jmp	draw_messages
.load_ok:
	mov	[debuggee_pid], eax
	mov	[bSuspended], 1
	push	ecx
	call	get_context
	mov	edi, oldcontext
	mov	ecx, 10
	rep	movsd
; activate debugger window
	pop	ecx
	mov	bl, 3
	push	18
	pop	eax
	int	40h
	call	redraw_title
	call	redraw_registers
	call	get_dump
	call	redraw_dump
	call	update_disasm_eip_force
	mov	esi, load_succ_msg
	push	[debuggee_pid]
	call	put_message_nodraw
	call	draw_messages
; now test for packed progs
	cmp	[disasm_buf_size], 100h
	jz	@f
	ret
@@:
	mov	esi, mxp_nrv_sig
	mov	ebp, disasm_buffer
	mov	edi, ebp
	push	3
	pop	ecx
	repz	cmpsb
	jnz	.not_mxp_nrv
	cmpsb
	mov	cl, mxp_nrv_sig_size-4
	repz	cmpsb
	mov	esi, mxp_nrv_name
	jz	.packed
.not_mxp_nrv:
	mov	esi, mxp_sig
	mov	edi, ebp
	mov	cl, mxp_sig_size
	repz	cmpsb
	mov	esi, mxp_name
	jz	.packed
.not_mxp:
	mov	esi, mxp_lzo_sig1
	mov	edi, ebp
	mov	cl, mxp_lzo_sig1_size
	repz	cmpsb
	mov	esi, mxp_lzo_name
	jz	.packed
	mov	esi, mxp_lzo_sig2
	mov	edi, ebp
	mov	cl, 8
	repz	cmpsb
	jnz	.not_mxp_lzo
	cmpsb
	mov	cl, mxp_lzo_sig2_size - 9
	repz	cmpsb
	mov	esi, mxp_lzo_name
	jz	.packed
.not_mxp_lzo:
	mov	esi, mtappack_name
	cmp	dword [ebp], 0xBF5E246A
	jnz	.not_mtappack
	cmp	dword [ebp+8], 0xEC4E8B57
	jnz	.not_mtappack1
	cmp	dword [ebp+12], 0x8D5EA4F3
	jnz	.not_mtappack1
	cmp	byte [ebp+12h], 0xE9
	jz	.packed
.not_mtappack1:
	cmp	word [ebp+8], 0xB957
	jnz	.not_mtappack
	cmp	dword [ebp+14], 0x575EA4F3
	jnz	.not_mtappack2
	cmp	byte [ebp+17h], 0xE9
	jz	.packed
.not_mtappack2:
	cmp	dword [ebp+14], 0x5F8DA4F3
	jnz	.not_mtappack3
	cmp	word [ebp+18], 0xE9FC
	jz	.packed
.not_mtappack3:
	cmp	word [ebp+14], 0xA4F3
	jnz	.not_mtappack
	cmp	byte [ebp+15h], 0xE9
	jz	.packed
.not_mtappack:
	ret
.packed:
	push	esi
	mov	esi, aPacked1
	call	put_message_nodraw
	pop	esi
	call	put_message_nodraw
	mov	esi, aPacked2
	call	put_message
	call	hide_cursor
	push	40
	pop	eax
	push	7
	pop	ebx
	int	40h
.wait:
	push	10
	pop	eax
	int	40h
	dec	eax
	jz	.redraw
	dec	eax
	jz	.key
	or	eax, -1
	int	40h
.redraw:
	call	draw_window
	call	hide_cursor
	jmp	.wait
.key:
	mov	al, 2
	int	40h
	cmp	ah, 'y'
	jz	.yes
	cmp	ah, 'Y'
	jz	.yes
	cmp	ah, 0xD
	jz	.yes
	cmp	ah, 'n'
	jz	.no
	cmp	ah, 'N'
	jnz	.wait
.no:
	push	40
	pop	eax
	mov	ebx, 0x107
	int	40h
	call	draw_cursor
	mov	esi, aN_str
	jmp	put_message
.yes:
	push	40
	pop	eax
	mov	ebx, 0x107
	int	40h
	call	draw_cursor
	mov	esi, aY_str
	call	put_message
	call	OnUnpack
	ret

mxp_nrv_sig:
	xor	eax, eax
	mov	ecx, 0x95	; 0xA1 for programs with parameters
	mov	[eax], ecx
	add	ecx, [eax+24h]
	push	40h
	pop	esi
	mov	edi, [eax+20h]
	push	edi
	rep	movsb
	jmp	dword [esp]
	pop	esi
	add	esi, [eax]
	xor	edi, edi
mxp_nrv_sig_size = $ - mxp_nrv_sig

mxp_sig:
	mov	ecx, 1CBh
	push	46h
	pop	esi
	mov	edi, [20h]
	rep	movsb
	mov	ecx, [24h]
	rep	movsb
	jmp	dword [20h]
	mov	eax, [20h]
	add	eax, 1CBh
	push	eax
	push	dword [24h]
	push	0
	push	8
	call	$+0x25
mxp_sig_size = $ - mxp_sig

mxp_lzo_sig1:
	xor	eax, eax
	mov	ebp, 0FFh
	mov	ecx, 175h
	mov	[eax], ecx
	add	ecx, [eax+24h]
	push	45h
	pop	esi
	mov	edi, [eax+20h]
	push	edi
	rep	movsb
	jmp	dword [esp]
	pop	ebx
	add	ebx, [eax]
	xor	edi, edi
	cmp	byte [ebx], 11h
	jbe	$+0x1A
mxp_lzo_sig1_size = $ - mxp_lzo_sig1
mxp_lzo_sig2:
	xor	eax, eax
	mov	ebp, 0FFh
	mov	ecx, 188h	; or 177h
	mov	[eax], ecx
	add	ecx, [eax+24h]
	push	44h
	pop	esi
	mov	edi, [eax+20h]
	rep	movsb
	jmp	dword [eax+20h]
	mov	ebx, [eax+20h]
	add	ebx, [eax]
mxp_lzo_sig2_size = $ - mxp_lzo_sig2

OnReload:
	cmp	[debuggee_pid], 0
	jnz	terminate_reload
	mov	esi, need_debuggee
	cmp	byte [loadname], 0
	jnz	do_reload
	jz	put_message
terminate_reload:
	mov	[bReload], 1
OnTerminate:
	mov	ecx, [debuggee_pid]
	push	8
	pop	ebx
	push	69
	pop	eax
	int	40h
	ret

AfterSuspend:
	mov	[bSuspended], 1
	call	get_new_context
	call	get_dump
	call	redraw_title
	call	redraw_registers
	call	redraw_dump
	call	update_disasm_eip
	ret

OnSuspend:
	mov	ecx, [debuggee_pid]
	push	4
	pop	ebx
	push	69
	pop	eax
	int	40h
	call	AfterSuspend
	mov	esi, aSuspended
	jmp	put_message
DoResume:
	mov	ecx, [debuggee_pid]
	push	5
	pop	ebx
	push	69
	pop	eax
	int	40h
	mov	[bSuspended], 0
	ret
OnResume:
	mov	esi, [curarg]
	cmp	byte [esi], 0
	jz	GoOn
	call	calc_expression
	jc	.ret
	mov	eax, ebp
	push	eax
	call	find_enabled_breakpoint
	pop	eax
	jz	GoOn
	mov	bl, 5	; valid enabled one-shot
	call	add_breakpoint
	jnc	GoOn
	mov	esi, aBreakpointLimitExceeded
	call	put_message
.ret:
	ret
GoOn:
; test for enabled breakpoint at eip
	mov	eax, [_eip]
	call	find_enabled_breakpoint
	jnz	.nobreak
; temporarily disable breakpoint, make step, enable breakpoint, continue
	inc	eax
	mov	[temp_break], eax
	mov	[bAfterGo], 1
	dec	eax
	call	disable_breakpoint
	call	get_context
	or	byte [_eflags+1], 1		; set TF
	call	set_context
	and	byte [_eflags+1], not 1
	call	DoResume
	ret
.nobreak:
	call	DoResume
	call	redraw_title
	call	redraw_registers
	call	redraw_dump
	ret
OnDetach:
	mov	ecx, [debuggee_pid]
	push	3
	pop	ebx
	push	69
	pop	eax
	int	40h
	and	[debuggee_pid], 0
	call	redraw_title
	call	redraw_registers
	call	redraw_dump
	mov	esi, aContinued
	jmp	put_message

after_go_exception:
	push	eax
	mov	eax, [temp_break]
	dec	eax
	push	esi
	call	enable_breakpoint
; in any case, clear TF and RF
	call	get_new_context
	and	[_eflags], not 10100h		; clear TF,RF
	call	set_context
	xor	edx, edx
	mov	[temp_break], edx
	xchg	dl, [bAfterGo]
	pop	esi
	pop	eax
	cmp	dl, 2
	jnz	@f
	lodsd
	push	esi
	call	get_dump
	jmp	exception.done
@@:	test	eax, eax
	jz	.notint1
; if exception is result of single step, simply ignore it and continue
	test	dword [esi], 0xF
	jnz	dbgmsgstart.5
	lodsd
	push	esi
	mov	esi, oldcontext
	mov	edi, context
	mov	ecx, 28h/4
	rep	movsd
	call	DoResume
	jmp	dbgmsgend
.notint1:
; in other case, work as without temp_break
	lodsd
	push	esi
	push	eax
	jmp	exception.4
.notour:

debugmsg:
	neg	[dbgbufsize]
	mov	esi, dbgbuf
dbgmsgstart:
	lodsd
;	push	eax esi
;	push	dword [esi]
;	mov	esi, dbgmsg_str
;	call	put_message_nodraw
;	pop	esi eax
	add	esi, 4
	dec	eax
	jz	exception
	dec	eax
	jz	terminated
	mov	[bSuspended], 1
	cmp	[bAfterGo], 0
	jnz	after_go_exception
	push	esi
	call	get_new_context
	and	[_eflags], not 10100h		; clear TF,RF
	call	set_context
	pop	esi
.5:
	push	esi
	call	get_dump
	pop	esi
	lodsd
	xor	ecx, ecx
.6:
	bt	eax, ecx
	jnc	.7
	mov	ebx, [drx_break+ecx*4]
	test	ebx, ebx
	jz	.7
	pushad
	dec	ebx
	push	ebx
	mov	esi, aBreakStop
	call	put_message_nodraw
	popad
.7:
	inc	ecx
	cmp	cl, 4
	jb	.6
	push	esi
	jmp	exception.done_draw
terminated:
	push	esi
	mov	esi, terminated_msg
	call	put_message
	and	[debuggee_pid], 0
	and	[temp_break], 0
	mov	[bAfterGo], 0
	xor	eax, eax
	mov	ecx, breakpoints_n*6/4+4
	mov	edi, breakpoints
	rep	stosd
	cmp	[bReload], 1
	sbb	[bReload], -1
	jmp	exception.done
exception:
	mov	[bSuspended], 1
	cmp	[bAfterGo], 0
	jnz	after_go_exception
	lodsd
	push	esi
	push	eax
	call	get_new_context
	and	[_eflags], not 10100h		; clear TF,RF
	call	set_context
.4:
	call	get_dump
	pop	eax
; int3 command generates exception 0D, #GP
	push	eax
	cmp	al, 0Dh
	jnz	.notdbg
; check for 0xCC byte at eip
	push	0
	push	69
	pop	eax
	push	6
	pop	ebx
	mov	ecx, [debuggee_pid]
	mov	edi, esp
	mov	esi, [_eip]
	push	1
	pop	edx
	int	40h
	pop	eax
	cmp	al, 0xCC
	jnz	.notdbg
; this is either dbg breakpoint or int3 cmd in debuggee
	mov	eax, [_eip]
	call	find_enabled_breakpoint
	jnz	.user_int3
; dbg breakpoint; clear if one-shot
	pop	ecx
	push	eax
	mov	esi, aBreakStop
	test	byte [edi+4], 4
	jz	.put_msg_eax
	pop	ecx
	call	clear_breakpoint
	jmp	.done
.user_int3:
	mov	eax, [_eip]
	inc	[_eip]
	pop	ecx
	push	eax
	call	set_context
	mov	esi, aUserBreak
	jmp	.put_msg_eax
.notdbg:
	mov	esi, aException
.put_msg_eax:
	call	put_message_nodraw
.done_draw:
	call	draw_messages
.done:
	push	18
	pop	eax
	push	3
	pop	ebx
	mov	ecx, [dbgwnd]
	int	40h	; activate dbg window
	call	redraw_title
	call	redraw_registers
	call	redraw_dump
	call	update_disasm_eip
dbgmsgend:
	pop	esi
	mov	ecx, [dbgbuflen]
	add	ecx, dbgbuf
	cmp	esi, ecx
	jnz	dbgmsgstart
	and	[dbgbuflen], 0
	neg	[dbgbufsize]
	cmp	[bReload], 2
	jnz	@f
	mov	[bReload], 0
	call	do_reload
@@:
	jmp	waitevent

CtrlF7:
	cmp	[debuggee_pid], 0
	jz	.no
	call	OnStep
.no:
	jmp	waitevent
CtrlF8:
	cmp	[debuggee_pid], 0
	jz	CtrlF7.no
	call	OnProceed
	jmp	CtrlF7.no

OnStep:
	cmp	[bSuspended], 0
	jz	.running
	call	get_context
	or	byte [_eflags+1], 1		; set TF
	call	set_context
	and	byte [_eflags+1], not 1
; if instruction at eip is "int xx", set one-shot breakpoint immediately after
	mov	eax, [_eip]
	call	find_enabled_breakpoint
	jnz	@f
	cmp	byte [edi+5], 0xCD
	jz	.int
@@:
	push	0
	push	69
	pop	eax
	push	6
	pop	ebx
	mov	ecx, [debuggee_pid]
	push	3
	pop	edx
	mov	edi, esp
	mov	esi, [_eip]
	int	40h
	cmp	eax, edx
	pop	eax
	jnz	.doit
	cmp	al, 0xCD
	jz	.int
; resume process
.doit:
	call	GoOn
	cmp	[bAfterGo], 0
	jz	@f
	mov	[bAfterGo], 2
@@:
	ret
.int:
	mov	eax, [_eip]
	inc	eax
	inc	eax
	push	eax
	call	find_enabled_breakpoint
	pop	eax
	jz	.doit
; there is no enabled breakpoint yet; set temporary breakpoint
	mov	bl, 5
	call	add_breakpoint
	jmp	.doit
.running:
	mov	esi, aRunningErr
	jmp	put_message

OnProceed:
	cmp	[bSuspended], 0
	jz	OnStep.running
	mov	esi, [_eip]
@@:
	call	get_byte_nobreak
	jc	OnStep
	inc	esi
; skip prefixes
	call	is_prefix
	jz	@b
	cmp	al, 0xE8	; call
	jnz	@f
	add	esi, 4
	jmp	.doit
@@:	; A4,A5 = movs, A6,A7=cmps
	cmp	al, 0xA4
	jb	@f
	cmp	al, 0xA8
	jb	.doit
@@:	; AA,AB=stos, AC,AD=lods, AE,AF=scas
	cmp	al, 0xAA
	jb	@f
	cmp	al, 0xB0
	jb	.doit
@@:	; E0=loopnz,E1=loopz,E2=loop
	cmp	al, 0xE0
	jb	.noloop
	cmp	al, 0xE2
	ja	.noloop
	inc	esi
	jmp	.doit
.noloop:	; FF /2 = call
	cmp	al, 0xFF
	jnz	OnStep
	call	get_byte_nobreak
	jc	OnStep
	inc	esi
	mov	cl, al
	and	al, 00111000b
	cmp	al, 00010000b
	jnz	OnStep
; skip instruction
	mov	al, cl
	and	eax, 7
	shr	cl, 6
	jz	.mod0
	jp	.doit
	cmp	al, 4
	jnz	@f
	inc	esi
@@:
	inc	esi
	dec	cl
	jz	@f
	add	esi, 3
@@:
	jmp	.doit
.mod0:
	cmp	al, 4
	jnz	@f
	call	get_byte_nobreak
	jc	OnStep
	inc	esi
	and	al, 7
@@:
	cmp	al, 5
	jnz	.doit
	add	esi, 4
.doit:
; insert one-shot breakpoint at esi and resume
	call	get_byte_nobreak
	jc	OnStep
	mov	eax, esi
	call	find_enabled_breakpoint
	jz	.ret
	mov	eax, esi
	mov	bl, 5
	call	add_breakpoint
	jmp	OnStep.doit
.ret:
	ret

get_byte_nobreak:
	mov	eax, esi
	call	find_enabled_breakpoint
	jnz	.nobreak
	mov	al, [edi+5]
	clc
	ret
.nobreak:
	push	69
	pop	eax
	push	6
	pop	ebx
	mov	ecx, [debuggee_pid]
	xor	edx, edx
	push	edx
	inc	edx
	mov	edi, esp
	int	40h
	dec	eax
	clc
	jz	@f
	stc
@@:	pop	eax
	ret

is_prefix:
	cmp	al, 0x64	; fs:
	jz	.ret
	cmp	al, 0x65	; gs:
	jz	.ret
	cmp	al, 0x66	; use16/32
	jz	.ret
	cmp	al, 0x67	; addr16/32
	jz	.ret
	cmp	al, 0xF0	; lock
	jz	.ret
	cmp	al, 0xF2	; repnz
	jz	.ret
	cmp	al, 0xF3	; rep(z)
	jz	.ret
	cmp	al, 0x2E	; cs:
	jz	.ret
	cmp	al, 0x36	; ss:
	jz	.ret
	cmp	al, 0x3E	; ds:
	jz	.ret
	cmp	al, 0x26	; es:
.ret:	ret

token_end	equ	1
token_reg	equ	2
token_hex	equ	3
token_add	equ	4
token_sub	equ	5
token_mul	equ	6
token_div	equ	7
token_lp	equ	8
token_rp	equ	9
token_err	equ	-1

is_hex_digit:
	cmp	al, '0'
	jb	.no
	cmp	al, '9'
	jbe	.09
	cmp	al, 'A'
	jb	.no
	cmp	al, 'F'
	jbe	.AF
	cmp	al, 'a'
	jb	.no
	cmp	al, 'f'
	jbe	.af
.no:
	stc
	ret
.09:
	sub	al, '0'
;	clc
	ret
.AF:
	sub	al, 'A'-10
;	clc
	ret
.af:
	sub	al, 'a'-10
;	clc
	ret

find_reg:
	mov	edi, reg_table
.findreg:
	movzx	ecx, byte [edi]
	stc
	jecxz	.regnotfound
	inc	edi
	push	esi edi ecx
@@:
	lodsb
	or	al, 20h
	scasb
	loopz	@b
	pop	ecx edi esi
	lea	edi, [edi+ecx+1]
	jnz	.findreg
	movzx	edi, byte [edi-1]
	add	esi, ecx
.regnotfound:
	ret

expr_get_token:
	lodsb
	cmp	al, 0
	jz	.end_token
	cmp	al, ' '
	jbe	expr_get_token
	cmp	al, '+'
	jz	.add
	cmp	al, '-'
	jz	.sub
	cmp	al, '*'
	jz	.mul
	cmp	al, '/'
	jz	.div
	cmp	al, '('
	jz	.lp
	cmp	al, ')'
	jnz	.notsign
.rp:
	mov	al, token_rp
	ret
.div:
	mov	al, token_div
	ret
.end_token:
	mov	al, token_end
	ret
.add:
	mov	al, token_add
	ret
.sub:
	mov	al, token_sub
	ret
.mul:
	mov	al, token_mul
	ret
.lp:
	mov	al, token_lp
	ret
.notsign:
	dec	esi
	call	find_reg
	jc	.regnotfound
	mov	al, token_reg
	ret
.regnotfound:
; test for hex number
	xor	ecx, ecx
	xor	edi, edi
	xor	eax, eax
@@:
	lodsb
	call	is_hex_digit
	jc	@f
	shl	edi, 4
	or	edi, eax
	inc	ecx
	jmp	@b
@@:
	dec	esi
	jecxz	.err
	cmp	ecx, 8
	ja	.err
	mov	al, token_hex
	ret
.err:
	mov	al, token_err
	mov	esi, aParseError
	ret

expr_read2:
	cmp	al, token_hex
	jz	.hex
	cmp	al, token_reg
	jz	.reg
	cmp	al, token_lp
	jz	.lp
	mov	al, token_err
	mov	esi, aParseError
	ret
.hex:
	mov	ebp, edi
.ret:
	jmp	expr_get_token
.reg:
	cmp	edi, 24
	jz	.eip
	sub	edi, 4
	jb	.8lo
	sub	edi, 4
	jb	.8hi
	sub	edi, 8
	jb	.16
	mov	ebp, [_eax+edi*4]
	jmp	.ret
.16:
	movzx	ebp, word [_eax+(edi+8)*4]
	jmp	.ret
.8lo:
	movzx	ebp, byte [_eax+(edi+4)*4]
	jmp	.ret
.8hi:
	movzx	ebp, byte [_eax+(edi+4)*4+1]
	jmp	.ret
.eip:
	mov	ebp, [_eip]
	jmp	.ret
.lp:
	call	expr_get_token
	call	expr_read0
	cmp	al, token_err
	jz	@f
	cmp	al, token_rp
	jz	expr_get_token
	mov	al, token_err
	mov	esi, aParseError
@@:	ret

expr_read1:
	call	expr_read2
.1:
	cmp	al, token_mul
	jz	.mul
	cmp	al, token_div
	jz	.div
	ret
.mul:
	push	ebp
	call	expr_get_token
	call	expr_read2
	pop	edx
; ebp := edx*ebp
	imul	ebp, edx
	jmp	.1
.div:
	push	ebp
	call	expr_get_token
	call	expr_read2
	pop	edx
; ebp := edx/ebp
	test	ebp, ebp
	jz	.div0
	push	eax
	xor	eax, eax
	xchg	eax, edx
	div	ebp
	xchg	eax, ebp
	pop	eax
	jmp	.1
.div0:
	mov	al, token_err
	mov	esi, aDivByZero
	ret

expr_read0:
	xor	ebp, ebp
	cmp	al, token_add
	jz	.add
	cmp	al, token_sub
	jz	.sub
	call	expr_read1
.1:
	cmp	al, token_add
	jz	.add
	cmp	al, token_sub
	jz	.sub
	ret
.add:
	push	ebp
	call	expr_get_token
	call	expr_read1
	pop	edx
; ebp := edx+ebp
	add	ebp, edx
	jmp	.1
.sub:
	push	ebp
	call	expr_get_token
	call	expr_read1
	pop	edx
; ebp := edx-ebp
	xchg	edx, ebp
	sub	ebp, edx
	jmp	.1

calc_expression:
; in: esi->expression
; out: CF=1 if error
;      CF=0 and ebp=value if ok
	call	expr_get_token
	call	expr_read0
	cmp	al, token_end
	jz	.end
	cmp	al, token_err
	jz	@f
	mov	esi, aParseError
@@:
	call	put_message
	stc
	ret
.end:
	clc
	ret

OnCalc:
	mov	esi, [curarg]
	call	calc_expression
	jc	.ret
	push	ebp
	mov	esi, calc_string
	call	put_message_nodraw
	jmp	draw_messages
.ret:
	ret

OnDump:
	mov	esi, [curarg]
	cmp	byte [esi], 0
	jnz	.param
	add	[dumppos], dump_height*10h
	jmp	.doit
.param:
	call	calc_expression
	jc	.ret
	mov	[dumppos], ebp
.doit:
	call	get_dump
	call	redraw_dump
.ret:
	ret

OnUnassemble:
	mov	esi, [curarg]
	cmp	byte [esi], 0
	jnz	.param
	mov	eax, [disasm_start_pos]
	mov	ecx, disasm_height
	mov	[disasm_cur_pos], eax
@@:
	push	ecx
	call	disasm_instr
	pop	ecx
	jc	.err
	loop	@b
	mov	eax, [disasm_cur_pos]
	jmp	.doit
.param:
	call	calc_expression
	jc	.ret
	mov	eax, ebp
.doit:
	push	eax
	push	[disasm_start_pos]
	mov	[disasm_start_pos], eax
	call	update_disasm
	pop	[disasm_start_pos]
	pop	eax
	cmp	[disasm_cur_str], 0
	jz	@f
	mov	[disasm_start_pos], eax
.ret:
	ret
@@:
	call	update_disasm
.err:
	mov	esi, aInvAddr
	jmp	put_message

OnReg:
	mov	esi, [curarg]
	call	skip_spaces
	call	find_reg
	jnc	@f
.err:
	mov	esi, RSyntax
	jmp	put_message
@@:
	call	skip_spaces
	test	al, al
	jz	.err
	cmp	al, '='
	jnz	@f
	inc	esi
	call	skip_spaces
	test	al, al
	jz	.err
@@:
	push	edi
	call	calc_expression
	pop	edi
	jc	.ret
; now edi=register id, ebp=value
	cmp	[bSuspended], 0
	mov	esi, aRunningErr
	jz	put_message
	xchg	eax, ebp
	cmp	edi, 24
	jz	.eip
	sub	edi, 4
	jb	.8lo
	sub	edi, 4
	jb	.8hi
	sub	edi, 8
	jb	.16
	mov	[_eax+edi*4], eax
	jmp	.ret
.16:
	mov	word [_eax+(edi+8)*4], ax
	jmp	.ret
.8lo:
	mov	byte [_eax+(edi+4)*4], al
	jmp	.ret
.8hi:
	mov	byte [_eax+(edi+4)*4+1], al
	jmp	.ret
.eip:
	mov	[_eip], eax
	call	update_disasm_eip
.ret:
	call	set_context
	jmp	redraw_registers

; Breakpoints manipulation
OnBp:
	mov	esi, [curarg]
	call	calc_expression
	jc	.ret
	xchg	eax, ebp
	push	eax
	call	find_breakpoint
	inc	eax
	pop	eax
	jz	.notfound
	mov	esi, aDuplicateBreakpoint
	jmp	.sayerr
.notfound:
	mov	bl, 1
	call	add_breakpoint
	jnc	.ret
	mov	esi, aBreakpointLimitExceeded
.sayerr:
	call	put_message
.ret:
	jmp	redraw_disasm

OnBpmb:
	mov	dh, 0011b
	jmp	DoBpm
OnBpmw:
	mov	dh, 0111b
	jmp	DoBpm
OnBpmd:
	mov	dh, 1111b
DoBpm:
	mov	esi, [curarg]
	cmp	byte [esi], 'w'
	jnz	@f
	and	dh, not 2
	inc	esi
@@:
	push	edx
	call	calc_expression
	pop	edx
	jnc	@f
	ret
@@:
; ebp=expression, dh=flags
	movzx	eax, dh
	shr	eax, 2
	test	ebp, eax
	jz	@f
	mov	esi, aUnaligned
	jmp	put_message
@@:
	mov	eax, ebp
	mov	bl, 0Bh
	call	add_breakpoint
	jnc	@f
	mov	esi, aBreakpointLimitExceeded
	jmp	put_message
@@:
; now find index
	push	eax
	xor	ecx, ecx
.l1:
	cmp	[drx_break+ecx*4], 0
	jnz	.l2
	push	69
	pop	eax
	push	ecx
	mov	dl, cl
	mov	ecx, [debuggee_pid]
	mov	esi, ebp
	push	9
	pop	ebx
	int	40h
	test	eax, eax
	jz	.ok
	pop	ecx
.l2:
	inc	ecx
	cmp	ecx, 4
	jb	.l1
	pop	eax
	call	clear_breakpoint
	mov	esi, aBreakpointLimitExceeded
	jmp	put_message
.ok:
	pop	ecx
	pop	eax
	and	byte [edi], not 2	; breakpoint is enabled
	shl	dl, 6
	or	dl, dh
	mov	byte [edi+1], dl
	inc	eax
	mov	[drx_break+ecx*4], eax
	ret

OnBc:
	mov	esi, [curarg]
@@:	call	get_hex_number
	jc	OnBp.ret
	call	clear_breakpoint
	jmp	@b

OnBd:
	mov	esi, [curarg]
@@:	call	get_hex_number
	jc	OnBp.ret
	call	disable_breakpoint
	jmp	@b

OnBe:
	mov	esi, [curarg]
@@:	call	get_hex_number
	jc	OnBp.ret
	push	eax
	call	find_enabled_breakpoint
	pop	eax
	jz	.err
	call	enable_breakpoint
	jmp	@b
.err:
	mov	esi, OnBeErrMsg
	jmp	put_message

get_hex_number:
	call	skip_spaces
	xor	ecx, ecx
	xor	edx, edx
@@:
	lodsb
	call	is_hex_digit
	jc	.ret
	shl	edx, 4
	or	dl, al
	inc	ecx
	jmp	@b
.ret:
	dec	esi
	cmp	ecx, 1
	xchg	eax, edx
	ret

OnBl:
	mov	esi, [curarg]
	cmp	byte [esi], 0
	jz	.listall
	call	get_hex_number
	jc	.ret
	cmp	eax, breakpoints_n
	jae	.err
	push	eax
	add	eax, eax
	lea	edi, [breakpoints + eax + eax*2]
	pop	eax
	test	byte [edi+4], 1
	jz	.err
	call	show_break_info
.ret:
	ret
.err:
	mov	esi, aInvalidBreak
	jmp	put_message
.listall:
	mov	edi, breakpoints
	xor	eax, eax
@@:
	test	byte [edi+4], 1
	jz	.cont
	push	edi eax
	call	show_break_info
	pop	eax edi
.cont:
	add	edi, 6
	inc	eax
	cmp	eax, breakpoints_n
	jb	@b
	ret

show_break_info:
	push	edi
	test	byte [edi+4], 8
	jnz	.dr
	push	dword [edi]
	push	eax
	mov	esi, aBreakNum
	call	put_message_nodraw
	jmp	.cmn
.dr:
	push	eax
	mov	esi, aMemBreak1
	call	put_message_nodraw
	pop	edi
	push	edi
	mov	esi, aMemBreak2
	test	byte [edi+5], 2
	jz	@f
	mov	esi, aMemBreak3
@@:
	call	put_message_nodraw
	pop	edi
	push	edi
	mov	esi, aMemBreak6
	test	byte [edi+5], 8
	jnz	@f
	mov	esi, aMemBreak5
	test	byte [edi+5], 4
	jnz	@f
	mov	esi, aMemBreak4
@@:
	call	put_message_nodraw
	pop	edi
	push	edi
	push	dword [edi]
	mov	esi, aMemBreak7
	call	put_message_nodraw
.cmn:
	pop	edi
	test	byte [edi+4], 2
	jz	@f
	push	edi
	mov	esi, aDisabled
	call	put_message_nodraw
	pop	edi
@@:
	test	byte [edi+4], 4
	jz	@f
	mov	esi, aOneShot
	call	put_message_nodraw
@@:
	mov	esi, newline
	jmp	put_message

add_breakpoint:
; in: eax=address, bl=flags
; out: CF=1 => error, CF=0 => eax=breakpoint number
	xor	ecx, ecx
	mov	edi, breakpoints
@@:
	test	byte [edi+4], 1
	jz	.found
	add	edi, 6
	inc	ecx
	cmp	ecx, breakpoints_n
	jb	@b
	stc
	ret
.found:
	stosd
	xchg	eax, ecx
	mov	[edi], bl
	test	bl, 2
	jnz	@f
	or	byte [edi], 2
	push	eax
	call	enable_breakpoint
	pop	eax
@@:
	clc
	ret

clear_breakpoint:
	cmp	eax, breakpoints_n
	jae	.ret
	mov	ecx, 4
	inc	eax
.1:
	cmp	[drx_break-4+ecx*4], eax
	jnz	@f
	and	[drx_break-4+ecx*4], 0
@@:	loop	.1
	dec	eax
	push	eax
	add	eax, eax
	lea	edi, [breakpoints + eax + eax*2 + 4]
	test	byte [edi], 1
	pop	eax
	jz	.ret
	push	edi
	call	disable_breakpoint
	pop	edi
	mov	byte [edi], 0
.ret:
	ret

disable_breakpoint:
	cmp	eax, breakpoints_n
	jae	.ret
	add	eax, eax
	lea	edi, [breakpoints + eax + eax*2 + 5]
	test	byte [edi-1], 1
	jz	.ret
	test	byte [edi-1], 2
	jnz	.ret
	or	byte [edi-1], 2
	test	byte [edi-1], 8
	jnz	.dr
	push	esi
	push	7
	pop	ebx
	push	69
	pop	eax
	mov	ecx, [debuggee_pid]
	xor	edx, edx
	inc	edx
	mov	esi, [edi-5]
	int	40h
	pop	esi
.ret:
	ret
.dr:
	mov	dl, [edi]
	shr	dl, 6
	mov	dh, 80h
	push	69
	pop	eax
	push	9
	pop	ebx
	mov	ecx, [debuggee_pid]
	int	40h
	ret

enable_breakpoint:
	push	esi
	cmp	eax, breakpoints_n
	jae	.ret
	add	eax, eax
	lea	edi, [breakpoints + eax + eax*2 + 5]
	test	byte [edi-1], 1
	jz	.ret
	test	byte [edi-1], 2
	jz	.ret
	and	byte [edi-1], not 2
	test	byte [edi-1], 8
	jnz	.dr
	push	6
	pop	ebx
	push	69
	pop	eax
	mov	esi, [edi-5]
	mov	ecx, [debuggee_pid]
	xor	edx, edx
	inc	edx
	int	40h
	dec	eax
	jnz	.err
	mov	al, 69
	push	0xCC
	mov	edi, esp
	inc	ebx
	int	40h
	pop	eax
.ret:
	pop	esi
	ret
.err:
	or	byte [edi-1], 2
	mov	esi, aBreakErr
	call	put_message
	pop	esi
	ret
.dr:
	push	9
	pop	ebx
	push	69
	pop	eax
	mov	esi, [edi-5]
	mov	ecx, [debuggee_pid]
	mov	dl, [edi]
	shr	dl, 6
	mov	dh, [edi]
	and	dh, 0xF
	int	40h
	test	eax, eax
	jnz	.err
	pop	esi
	ret

find_breakpoint:
	xor	ecx, ecx
	xchg	eax, ecx
	mov	edi, breakpoints
@@:
	test	byte [edi+4], 1
	jz	.cont
	test	byte [edi+4], 8
	jnz	.cont
	cmp	[edi], ecx
	jz	.found
.cont:
	add	edi, 6
	inc	eax
	cmp	eax, breakpoints_n
	jb	@b
	or	eax, -1
.found:
	ret

find_enabled_breakpoint:
	xor	ecx, ecx
	xchg	eax, ecx
	mov	edi, breakpoints
@@:
	test	byte [edi+4], 1
	jz	.cont
	test	byte [edi+4], 2 or 8
	jnz	.cont
	cmp	[edi], ecx
	jz	.found
.cont:
	add	edi, 6
	inc	eax
	cmp	eax, breakpoints_n
	jb	@b
	or	eax, -1
.found:
	ret

OnUnpack:
; program must be loaded - checked when command was parsed
; program must be stopped
	mov	esi, aRunningErr
	cmp	[bSuspended], 0
	jz	put_message
; all breakpoints must be disabled
	mov	edi, breakpoints
@@:
	test	byte [edi+4], 1
	jz	.cont
	test	byte [edi+4], 2
	jnz	.cont
	mov	esi, aEnabledBreakErr
	jmp	put_message
.cont:
	add	edi, 6
	cmp	edi, breakpoints+breakpoints_n*6
	jb	@b
; ok, now do it
; set breakpoint on 0xC dword access
	push	9
	pop	ebx
	mov	ecx, [debuggee_pid]
	mov	dx, 1111b*256
	push	0xC
	pop	esi
@@:
	push	69
	pop	eax
	int	40h
	test	eax, eax
	jz	.breakok
	inc	edx
	cmp	dl, 4
	jb	@b
.breakok:
	call	GoOn
; now wait for event
.wait:
	push	10
	pop	eax
	int	40h
	dec	eax
	jz	.redraw
	dec	eax
	jz	.key
	dec	eax
	jnz	.debug
; button; we have only one button, close
	or	eax, -1
	int	40h
.redraw:
	call	draw_window
	jmp	.wait
.key:
	mov	al, 2
	int	40h
	cmp	ah, 3	; Ctrl+C
	jnz	.wait
.userbreak:
	mov	esi, aInterrupted
.x1:
	push	edx esi
	call	put_message
	pop	esi edx
	or	dh, 80h
	push	69
	pop	eax
	push	9
	pop	ebx
	mov	ecx, [debuggee_pid]
	int	40h
	cmp	esi, aUnpacked
	jnz	OnSuspend
	jmp	AfterSuspend
.debug:
	cmp	[dbgbuflen], 4*3
	jnz	.notour
	cmp	dword [dbgbuf], 3
	jnz	.notour
	test	byte [dbgbuf+8], 1
	jnz	.our
.notour:
	mov	esi, aInterrupted
	push	edx
	call	put_message
	pop	edx
	or	dh, 80h
	push	69
	pop	eax
	push	9
	pop	ebx
	mov	ecx, [debuggee_pid]
	int	40h
	jmp	debugmsg
.our:
	and	[dbgbuflen], 0
	push	edx
	call	get_context
	push	eax
	mov	al, 69
	mov	bl, 6
	mov	ecx, [debuggee_pid]
	mov	edi, esp
	push	4
	pop	edx
	push	0xC
	pop	esi
	int	40h
	pop	eax
	pop	edx
	cmp	eax, [_eip]
	jz	.done
	call	DoResume
	jmp	.wait
.done:
	mov	esi, aUnpacked
	jmp	.x1

disasm_get_byte:
; out: al=byte
	push	ecx
	mov	ecx, [disasm_cur_pos]
	sub	ecx, [disasm_start_pos]
	cmp	ecx, [disasm_buf_size]
	jae	disasm_err
	mov	al, [disasm_buffer+ecx]
	pop	ecx
	inc	[disasm_cur_pos]
	ret
disasm_get_word:
	push	ecx
	mov	ecx, [disasm_cur_pos]
	sub	ecx, [disasm_start_pos]
	inc	ecx
	cmp	ecx, [disasm_buf_size]
	jae	disasm_err
	mov	ax, word [disasm_buffer-1+ecx]
	pop	ecx
	add	[disasm_cur_pos], 2
	ret
disasm_get_dword:
	push	ecx
	mov	ecx, [disasm_cur_pos]
	sub	ecx, [disasm_start_pos]
	add	ecx, 3
	cmp	ecx, [disasm_buf_size]
	jae	disasm_err
	mov	eax, dword [disasm_buffer-3+ecx]
	pop	ecx
	add	[disasm_cur_pos], 4
	ret

disasm_err:
	mov	esp, ebp
stc_ret:
	stc
	ret
disasm_ret:
	mov	esp, ebp
	and	byte [edi], 0
	ret

disasm_instr:
	mov	ebp, esp
	cmp	[debuggee_pid], 0
	jz	stc_ret
	mov	edi, disasm_string
	xor	ecx, ecx
; ecx=flags
disasm_loop1:
	xor	eax, eax
	call	disasm_get_byte
	jmp	dword [disasm_table_1 + eax*4]

cop0:
clock:
crepnz:
crep:
csegcs:
csegds:
cseges:
csegss:
csegfs:
cseggs:
	call	@f
	db	0x2E,3,'cs:'
	db	0x36,3,'ss:'
	db	0x3E,3,'ds:'
	db	0x26,3,'es:'
	db	0x64,3,'fs:'
	db	0x65,3,'gs:'
	db	0x06,10,'push    es'
	db	0x07,10,'pop     es'
	db	0x0E,10,'push    cs'
	db	0x16,10,'push    ss'
	db	0x17,10,'pop     ss'
	db	0x1E,10,'push    ds'
	db	0x1F,10,'pop     ds'
	db	0x27,3,'daa'
	db	0x2F,3,'das'
	db	0x37,3,'aaa'
	db	0x3F,3,'aas'
	db	0x60,6,0,'pusha'
	db	0x61,5,0,'popa'
	db	0x90,3,'nop'
	db	0x9B,5,'fwait'
	db	0x9C,6,0,'pushf'
	db	0x9D,5,0,'popf'
	db	0x9E,4,'sahf'
	db	0x9F,4,'lahf'
	db	0xA4,5,'movsb'
	db	0xA5,5,0,'movs'
	db	0xA6,5,'cmpsb'
	db	0xA7,5,0,'cmps'
	db	0xAA,5,'stosb'
	db	0xAB,5,0,'stos'
	db	0xAC,5,'lodsb'
	db	0xAD,5,0,'lods'
	db	0xAE,5,'scasb'
	db	0xAF,5,0,'scas'
	db	0xC3,3,'ret'
	db	0xC9,5,'leave'
	db	0xCC,4,'int3'
	db	0xF0,4,'lock'
	db	0xF2,5,'repnz'
	db	0xF3,6,'rep(z)'
	db	0xF5,3,'cmc'
	db	0xF8,3,'clc'
	db	0xF9,3,'stc'
	db	0xFA,3,'cli'
	db	0xFB,3,'sti'
	db	0xFC,3,'cld'
	db	0xFD,3,'std'
@@:
	pop	esi
@@:
	cmp	al, [esi]
	jz	.found
	inc	esi
	movzx	edx, byte [esi]
	inc	esi
	add	esi, edx
	jmp	@b
.found:
	inc	esi
	lodsb
	cmp	byte [esi], 0
	jz	@f
	movzx	ecx, al
disasm_1:
	rep	movsb
	and	byte [edi], 0
	ret
@@:
	mov	dl, ch
	movzx	ecx, al
	dec	ecx
	inc	esi
	rep	movsb
	test	dl, 1
	mov	al, 'w'
	jnz	@f
	mov	al, 'd'
@@:	stosb
	and	byte [edi], 0
	ret

c67:
	or	ch, 2
	jmp	disasm_loop1
c66:
	or	ch, 1
	jmp	disasm_loop1

center:
caam:
cxlat:
crdtsc:
csysenter:
ccpuid:
ccmpxchg:
cbsf:
cbsr:
ccmpxchg8b:
cunk:
cerr:
	mov	eax, '???'
	stosd
	clc
	ret

cF:
	call	disasm_get_byte
	jmp	dword [disasm_table_2 + eax*4]

macro disasm_set_modew
{
	test	al, 1
	jz	@f
	or	ch, 80h
@@:
}

cmov2:
	disasm_set_modew
; mov r/m,i
	call	disasm_get_byte
	dec	[disasm_cur_pos]
	test	al, 00111000b
	jnz	cunk
	mov	eax, 'mov '
	stosd
	mov	eax, '    '
	stosd
	call	disasm_readrmop
	mov	ax, ', '
	stosw
	xor	eax, eax
	test	ch, 80h
	jnz	.1
	call	disasm_get_byte
	jmp	.3
.1:
	test	ch, 1
	jnz	.2
	call	disasm_get_dword
	jmp	.3
.2:
	call	disasm_get_word
.3:
	call	disasm_write_num
	and	byte [edi], 0
	ret

cret2:
	mov	eax, 'ret '
	stosd
	mov	eax, '    '
	stosd
	xor	eax, eax
	jmp	cmov2.2

disasm_write_num:
	push	ecx eax
	inc	edi
@@:
	mov	ecx, eax
	shr	eax, 4
	jz	@f
	inc	edi
	jmp	@b
@@:
	pop	eax
	cmp	ecx, 10
	jb	@f
	inc	edi
@@:
	push	edi eax
@@:
	mov	ecx, eax
	and	al, 0xF
	cmp	al, 10
	sbb	al, 69h
	das
	dec	edi
	mov	[edi], al
	mov	eax, ecx
	shr	eax, 4
	jnz	@b
	cmp	ecx, 10
	jb	@f
	mov	byte [edi-1], '0'
@@:
	pop	eax edi ecx
	cmp	eax, 10
	jb	@f
	mov	byte [edi], 'h'
	inc	edi
@@:
	ret

label disasm_regs32 dword
label disasm_regs dword
	db	'eax',0
	db	'ecx',0
	db	'edx',0
	db	'ebx',0
	db	'esp',0
	db	'ebp',0
	db	'esi',0
	db	'edi',0
disasm_regs16	dw	'ax','cx','dx','bx','sp','bp','si','di'
disasm_regs8	dw	'al','cl','dl','bl','ah','ch','dh','bh'
disasm_scale	db	'1248'
disasm_readrmop:
	call	disasm_get_byte
	test	ch, 40h
	jnz	.skip_size
	push	eax
	and	al, 0xC0
	cmp	al, 0xC0
	pop	eax
	jz	.skip_size
	test	ch, 80h
	jz	.byte
	test	ch, 1
	jnz	.word
	mov	dword [edi], 'dwor'
	mov	byte [edi+4], 'd'
	inc	edi
	jmp	@f
.byte:
	test	ch, 20h
	jz	.qb
	mov	byte [edi], 't'
	inc	edi
.qb:
	mov	dword [edi], 'byte'
	jmp	@f
.word:
	test	ch, 20h
	jz	.qw
	mov	byte [edi], 'q'
	inc	edi
.qw:
	mov	dword [edi], 'word'
@@:
	mov	byte [edi+4], ' '
	add	edi, 5
.skip_size:
	test	ch, 2
	jnz	disasm_readrmop16
	push	ecx
	movzx	ecx, al
	and	eax, 7
	shr	ecx, 6
	jz	.vmod0
	jp	.vmod3
	mov	byte [edi], '['
	inc	edi
	cmp	al, 4
	jz	.sib1
	mov	eax, [disasm_regs+eax*4]
	stosd
	dec	edi
	jmp	@f
.sib1:
	call	.parse_sib
@@:
	mov	al, '+'
	stosb
	dec	ecx
	jz	.vmod1
	call	disasm_get_dword
	jmp	@f
.vmod1:
	call	disasm_get_byte
	movsx	eax, al
@@:
	test	eax, eax
	jns	.2
	neg	eax
	mov	byte [edi-1], '-'
.2:
	call	disasm_write_num
	mov	al, ']'
	stosb
	pop	ecx
	ret
.vmod3:
	pop	ecx
	test	ch, 80h
	jz	.vmod3_byte
	test	ch, 1
	jnz	.vmod3_word
	test	ch, 20h
	jnz	.vmod3_sti
	mov	eax, [disasm_regs32+eax*4]
	stosd
	dec	edi
	ret
.vmod3_byte:
	mov	ax, [disasm_regs8+eax*2]
@@:
	stosw
	ret
.vmod3_word:
	mov	ax, [disasm_regs16+eax*2]
	jmp	@b
.vmod3_sti:
	mov	word [edi], 'st'
	add	al, '0'
	mov	byte [edi+2], al
	add	edi, 3
	ret
.vmod0:
	mov	byte [edi], '['
	inc	edi
	cmp	al, 4
	jz	.sib2
	cmp	al, 5
	jz	.ofs32
	mov	eax, [disasm_regs+eax*4]
	stosd
	mov	byte [edi-1], ']'
	pop	ecx
	ret
.ofs32:
	call	disasm_get_dword
	jmp	.2
.sib2:
	call	.parse_sib
	mov	al, ']'
	stosb
	pop	ecx
	ret
.parse_sib:
	call	disasm_get_byte
	push	edx
	mov	dl, al
	mov	dh, 0
	and	eax, 7
	cmp	al, 5
	jnz	@f
	jecxz	.sib0
@@:
	mov	eax, [disasm_regs+eax*4]
	stosd
	dec	edi
	mov	dh, 1
.sib0:
	mov	al, dl
	shr	eax, 3
	and	eax, 7
	cmp	al, 4
	jz	.sibret
	test	dh, dh
	jz	@f
	mov	byte [edi], '+'
	inc	edi
@@:
	mov	eax, [disasm_regs+eax*4]
	stosd
	dec	edi
	shr	dl, 6
	jz	@f
	mov	al, '*'
	stosb
	movzx	eax, dl
	mov	al, [disasm_scale+eax]
	stosb
@@:
.sibret:
	test	dh, dh
	jnz	.sibret2
	call	disasm_get_dword
	cmp	byte [edi-1], '['
	jz	@f
	mov	byte [edi], '+'
	test	eax, eax
	jns	.sibns
	neg	eax
	mov	byte [edi], '-'
.sibns:
	inc	edi
@@:
	call	disasm_write_num
.sibret2:
	pop	edx
	ret

disasm_rm16_1	dd	'bxsi','bxdi','bpsi','bpdi'
disasm_rm16_2	dw	'si','di','bp','bx'
disasm_readrmop16:
	push	ecx
	movzx	ecx, al
	and	eax, 7
	shr	ecx, 6
	jz	.vmod0
	jp	disasm_readrmop.vmod3	; mod=3 is the same in 16- and 32-bit code
; 1 or 2
	mov	byte [edi], '['
	inc	edi
	cmp	al, 4
	jae	@f
	mov	eax, [disasm_rm16_1+eax*4]
	stosw
	mov	al, '+'
	stosb
	shr	eax, 16
	jmp	.1
@@:
	mov	eax, dword [disasm_rm16_2+eax*2-4*2]
.1:
	stosw
	mov	al, '+'
	stosb
	xor	eax, eax
	dec	ecx
	jnz	.2
	call	disasm_get_byte
	cbw
	jmp	@f
.2:
	call	disasm_get_word
@@:
	test	ax, ax
	jns	@f
	mov	byte [edi-1], '-'
	neg	ax
@@:
	call	disasm_write_num
.done1:
	mov	al, ']'
	stosb
	pop	ecx
	ret
.vmod0:
	mov	byte [edi], '['
	inc	edi
	cmp	al, 6
	jz	.ofs16
	cmp	al, 4
	jae	@f
	mov	eax, [disasm_rm16_1+eax*4]
	stosw
	mov	al, '+'
	stosb
	shr	eax, 16
	jmp	.3
@@:
	mov	eax, dword [disasm_rm16_2+eax*2-4*2]
.3:
	stosw
	jmp	.done1
.ofs16:
	xor	eax, eax
	call	disasm_get_word
	call	disasm_write_num
	jmp	.done1

cpush21:
	mov	eax, 'push'
	stosd
	mov	eax, '    '
	stosd
disasm_i32:
	call	disasm_get_dword
	call	disasm_write_num
	and	byte [edi], 0
	ret

cpush22:
	mov	eax, 'push'
	stosd
	mov	eax, '    '
	stosd
	call	disasm_get_byte
	movsx	eax, al
	call	disasm_write_num
	and	byte [edi], 0
	ret

cinc1:
; inc reg32
cdec1:
; dec reg32
cpush1:
; push reg32
cpop1:
; pop reg32
cbswap:
; bswap reg32
	mov	edx, eax
	and	edx, 7
	shr	eax, 3
	sub	al, 8
	mov	esi, 'inc '
	jz	@f
	mov	esi, 'dec '
	dec	al
	jz	@f
	mov	esi, 'push'
	dec	al
	jz	@f
	mov	esi, 'pop '
	dec	al
	jz	@f
	mov	esi, 'bswa'
@@:
	xchg	eax, esi
	stosd
	mov	eax, '    '
	jz	@f
	mov	al, 'p'
@@:
	stosd
	xchg	eax, edx
	call	disasm_write_reg1632
	and	byte [edi], 0
	ret

cxchg1:
; xchg eax,reg32
	and	eax, 7
	xchg	eax, edx
	mov	eax, 'xchg'
	stosd
	mov	eax, '    '
	stosd
	xor	eax, eax
	call	disasm_write_reg1632
	mov	ax, ', '
	stosw
	xchg	eax, edx
	call	disasm_write_reg1632
	and	byte [edi], 0
	ret

cint:
	mov	eax, 'int '
	stosd
	mov	eax, '    '
	stosd
disasm_i8u:
	xor	eax, eax
	call	disasm_get_byte
	call	disasm_write_num
	and	byte [edi], 0
	ret

cmov11:
; mov r8,i8
	mov	ecx, eax
	mov	eax, 'mov '
	stosd
	mov	eax, '    '
	stosd
	and	ecx, 7
	mov	ax, [disasm_regs8+ecx*2]
	stosw
	mov	ax, ', '
	stosw
	jmp	disasm_i8u

cmov12:
; mov r32,i32
	xchg	eax, edx
	mov	eax, 'mov '
	stosd
	mov	eax, '    '
	stosd
	xchg	eax, edx
	and	eax, 7
	call	disasm_write_reg1632
	mov	ax, ', '
	stosw
	jmp	cmov2.1

disasm_shifts	dd	'rol ','ror ','rcl ','rcr ','shl ','shr ','sal ','sar '
cshift2:
; shift r/m,1 = D0/D1
cshift3:
; shift r/m,cl = D2/D3
	disasm_set_modew
	mov	dl, al
	call	disasm_get_byte
	dec	[disasm_cur_pos]
	shr	al, 3
	and	eax, 7
	mov	eax, [disasm_shifts+eax*4]
	stosd
	mov	eax, '    '
	stosd
	call	disasm_readrmop
	cmp	dl, 0xD2
	jb	.s1
	mov	eax, ', cl'
	stosd
	and	byte [edi], 0
	ret
.s1:
	mov	eax, ', 1'
	stosd
	clc
	ret

cshift1:
; shift r/m,i8 = C0/C1
	disasm_set_modew
	call	disasm_get_byte
	dec	[disasm_cur_pos]
	shr	al, 3
	and	eax, 7
	mov	eax, [disasm_shifts+eax*4]
	stosd
	mov	eax, '    '
	stosd
	call	disasm_readrmop
	mov	ax, ', '
	stosw
	jmp	disasm_i8u


cmov3:
; A0: mov al,[ofs32]
; A1: mov ax/eax,[ofs32]
; A2: mov [ofs32],al
; A3: mov [ofs32],ax/eax
	mov	edx, 'mov '
	xchg	eax, edx
	stosd
	mov	eax, '    '
	stosd
	test	dl, 2
	jnz	.1
	call	.write_acc
	mov	ax, ', '
	stosw
	call	.write_ofs32
	jmp	.2
.1:
	call	.write_ofs32
	mov	ax, ', '
	stosw
	call	.write_acc
.2:	and	byte [edi], 0
	ret
.write_acc:
	test	dl, 1
	jz	.8bit
	test	ch, 1
	jnz	.16bit
	mov	eax, 'eax'
	stosd
	dec	edi
	ret
.16bit:
	mov	ax, 'ax'
	stosw
	ret
.8bit:
	mov	ax, 'al'
	stosw
	ret
.write_ofs32:
	mov	al, '['
	stosb
	call	disasm_get_dword
	call	disasm_write_num
	mov	al, ']'
	stosb
	ret

disasm_write_reg:
	test	ch, 80h
	jnz	disasm_write_reg1632
	mov	ax, [disasm_regs8+eax*2]
	stosw
	ret
disasm_write_reg1632:
	test	ch, 1
	jnz	@f
	mov	eax, [disasm_regs32+eax*4]
	stosd
	dec	edi
	ret
@@:
	mov	ax, [disasm_regs16+eax*2]
	stosw
	ret

cmovzx:		; 0F B6/B7
cmovsx:		; 0F BE/BF
	mov	edx, eax
	disasm_set_modew
	mov	eax, 'movz'
	cmp	dl, 0xB8
	jb	@f
	mov	eax, 'movs'
@@:
	stosd
	mov	eax, 'x   '
	stosd
	call	disasm_get_byte
	dec	[disasm_cur_pos]
	shr	al, 3
	and	eax, 7
	call	disasm_write_reg1632
	mov	ax, ', '
	stosw
	or	ch, 1	; 2nd operand - 8 or 16 bits
	call	disasm_readrmop
	and	byte [edi], 0
	ret

disasm_op2cmds	dd 'add ','or  ','adc ','sbb ','and ','sub ','xor ','cmp '
cop21:
	disasm_set_modew
	mov	esi, 'test'
	cmp	al, 0A8h
	jae	@f
	shr	al, 3
	and	eax, 7
	mov	esi, [disasm_op2cmds+eax*4]
@@:
	xchg	eax, esi
	stosd
	mov	eax, '    '
	stosd
	test	ch, 80h
	jnz	.1632
	mov	eax, 'al, '
	stosd
	jmp	disasm_i8u
.1632:
	test	ch, 1
	jnz	.16
	mov	eax, 'eax,'
	stosd
	mov	al, ' '
	stosb
	call	disasm_get_dword
	jmp	.x
.16:
	mov	eax, 'ax, '
	stosd
	xor	eax, eax
	call	disasm_get_word
.x:
	call	disasm_write_num
	and	byte [edi], 0
	ret

cop22:
	disasm_set_modew
	or	ch, 40h
	mov	edx, eax
	mov	esi, 'lea '
	cmp	al, 8Dh
	jz	@f
	mov	esi, 'imul'
	cmp	al, 0xAF
	jz	@f
	mov	esi, 'mov '
	cmp	al, 88h
	jae	@f
	mov	esi, 'xchg'
	cmp	al, 86h
	jae	@f
	mov	esi, 'test'
	cmp	al, 84h
	jae	@f
	shr	al, 3
	and	eax, 7
	mov	esi, [disasm_op2cmds+eax*4]
@@:
	xchg	eax, esi
	stosd
	mov	eax, '    '
	stosd
	call	disasm_get_byte
	dec	[disasm_cur_pos]
	shr	al, 3
	and	eax, 7
	cmp	dl, 0x8D
	jz	@f
	cmp	dl, 0x86
	jz	@f
	cmp	dl, 0x87
	jz	@f
	test	dl, 2
	jz	.d0
@@:
	call	disasm_write_reg
	mov	ax, ', '
	stosw
	call	disasm_readrmop
	and	byte [edi], 0
	ret
.d0:
	push	eax
	call	disasm_readrmop
	mov	ax, ', '
	stosw
	pop	eax
	call	disasm_write_reg
	and	byte [edi], 0
	ret

cop23:
	disasm_set_modew
	xchg	eax, edx
	call	disasm_get_byte
	dec	[disasm_cur_pos]
	shr	eax, 3
	and	eax, 7
	mov	eax, [disasm_op2cmds+eax*4]
ctest:
	stosd
	mov	eax, '    '
	stosd
	call	disasm_readrmop
	mov	ax, ', '
	stosw
	test	ch, 80h
	jz	.i8
	cmp	dl, 83h
	jz	.i8
	test	ch, 1
	jnz	.i16
	call	disasm_get_dword
	jmp	.ic
.i8:
	xor	eax, eax
	call	disasm_get_byte
	cmp	dl, 83h
	jnz	.ic
	movsx	eax, al
	jmp	.ic
.i16:
	xor	eax, eax
	call	disasm_get_word
.ic:
	call	disasm_write_num
	and	byte [edi], 0
	ret

cbtx1:
; btx r/m,i8 = 0F BA
	or	ch, 80h
	call	disasm_get_byte
	dec	[disasm_cur_pos]
	shr	al, 3
	and	eax, 7
	cmp	al, 4
	jb	cunk
	mov	eax, [btx1codes+eax*4-4*4]
	stosd
	mov	eax, '    '
	stosd
	call	disasm_readrmop
	mov	ax, ', '
	stosw
	jmp	disasm_i8u
btx1codes	dd	'bt  ','bts ','btr ','btc '
cbtx2:
; btx r/m,r = 0F 101xx011 (A3,AB,B3,BB)
	shr	al, 3
	and	eax, 3
	mov	eax, [btx1codes+eax*4]
	stosd
	mov	eax, '    '
	stosd
	or	ch, 0xC0
	call	disasm_get_byte
	dec	[disasm_cur_pos]
	shr	al, 3
	and	eax, 7
	push	eax
	call	disasm_readrmop
	mov	ax, ', '
	stosw
	pop	eax
	call	disasm_write_reg1632
	and	byte [edi], 0
	ret

csetcc:
	and	eax, 0xF
	mov	ax, [disasm_jcc_codes + eax*2]
	mov	dword [edi], 'setc'
	add	edi, 3
	stosw
	mov	ax, '  '
	stosw
	stosb
	call	disasm_readrmop
	and	byte [edi], 0
	ret

disasm_jcc_codes dw 'o ','no','b ','ae','z ','nz','be','a ','s ','ns','p ','np','l ','ge','le','g '
cjcc1:
cjmp2:
	cmp	al, 0xEB
	jz	.1
	and	eax, 0xF
	mov	ax, [disasm_jcc_codes + eax*2]
	jmp	.2
.1:
	mov	ax, 'mp'
.2:
	mov	byte [edi], 'j'
	inc	edi
	stosw
	mov	eax, '    '
	stosb
	stosd
	call	disasm_get_byte
	movsx	eax, al
disasm_rva:
	add	eax, [disasm_cur_pos]
	call	disasm_write_num
	and	byte [edi], 0
	ret

ccall1:
cjmp1:
cjcc2:
	mov	edx, 'call'
	cmp	al, 0xE8
	jz	@f
	mov	edx, 'jmp '
	cmp	al, 0xE9
	jz	@f
	mov	edx, '    '
	and	eax, 0xF
	mov	dx, [disasm_jcc_codes+eax*2]
	shl	edx, 8
	mov	dl, 'j'
@@:
	xchg	eax, edx
	stosd
	mov	eax, '    '
	stosd
	call	disasm_get_dword
	jmp	disasm_rva

op11codes	dd	'test',0,'not ','neg ','mul ','imul','div ','idiv'
op12codes	dd	'inc ','dec ','call',0,'jmp ',0,'push',0
cop1:
	disasm_set_modew
	xchg	eax, edx
	call	disasm_get_byte
	dec	[disasm_cur_pos]
	shr	al, 3
	and	eax, 7
	cmp	dl, 0xFE
	jnz	@f
	cmp	al, 1
	ja	cunk
@@:
	and	edx, 8
	add	eax, edx
	mov	eax, [op11codes+eax*4]
	test	eax, eax
	jz	cunk
	cmp	eax, 'test'
	jz	ctest
@@:
	stosd
	mov	eax, '    '
	stosd
	call	disasm_readrmop
	and	byte [edi], 0
	ret

cpop2:
	or	ch, 80h
	call	disasm_get_byte
	dec	[disasm_cur_pos]
	test	al, 00111000b
	jnz	cunk
	mov	eax, 'pop '
	jmp	@b

cloopnz:
	mov	eax, 'loop'
	stosd
	mov	eax, 'nz  '
	test	ch, 2
	jz	@f
	mov	ah, 'w'
@@:	jmp	cloop.cmn
cloopz:
	mov	eax, 'loop'
	stosd
	mov	eax, 'z   '
	test	ch, 2
	jz	@f
	mov	eax, 'zw  '
@@:	jmp	cloop.cmn

cjcxz:
cloop:
	cmp	al, 0xE2
	jz	.loop
	test	ch, 2
	jnz	.jcxz
	mov	eax, 'jecx'
	stosd
	mov	eax, 'z   '
	jmp	.cmn
.jcxz:
	mov	eax, 'jcxz'
	stosd
	mov	eax, '    '
	jmp	.cmn
.loop:
	mov	eax, 'loop'
	stosd
	mov	eax, '    '
	test	ch, 2
	jz	.cmn
	mov	al, 'w'
.cmn:
	stosd
	call	disasm_get_byte
	movsx	eax, al
	add	eax, [disasm_cur_pos]
	test	ch, 1
	jz	@f
	and	eax, 0xFFFF
@@:
disasm_write_num_done:
	call	disasm_write_num
	and	byte [edi], 0
	ret

cimul1:
; imul r,r/m,i
	or	ch, 80h		; 32bit operation
	xchg	eax, edx
	mov	eax, 'imul'
	stosd
	mov	eax, '    '
	stosd
	call	disasm_get_byte
	dec	[disasm_cur_pos]
	shr	al, 3
	and	eax, 7
	call	disasm_write_reg1632
	mov	ax, ', '
	stosw
	call	disasm_readrmop
	mov	ax, ', '
	stosw
	test	ch, 1
	jnz	.16
	cmp	dl, 0x69
	jz	.op32
	call	disasm_get_byte
	movsx	eax, al
	jmp	disasm_write_num_done
.op32:
	call	disasm_get_dword
	jmp	disasm_write_num_done
.16:
	cmp	dl, 0x69
	jz	.op16
	call	disasm_get_byte
	cbw
	jmp	disasm_write_num_done
.op16:
	xor	eax, eax
	call	disasm_get_word
	jmp	disasm_write_num_done

cshld:
cshrd:
	mov	edx, 'shld'
	test	al, 8
	jz	@f
	mov	edx, 'shrd'
@@:
	xchg	eax, edx
	stosd
	mov	eax, '    '
	stosd
	call	disasm_get_byte
	dec	[disasm_cur_pos]
	shr	al, 3
	and	eax, 7
	push	eax
	or	ch, 80h
	call	disasm_readrmop
	mov	ax, ', '
	stosw
	pop	eax
	call	disasm_write_reg1632
	mov	ax, ', '
	stosw
	test	dl, 1
	jz	disasm_i8u
	mov	ax, 'cl'
	stosw
	and	byte [edi], 0
	ret

ccbw:
	mov	eax, 'cbw '
	test	ch, 1
	jnz	@f
	mov	eax, 'cwde'
@@:	stosd
	and	byte [edi+1], 0
	ret
ccwd:
	mov	eax, 'cwd '
	test	ch, 1
	jnz	@b
	mov	eax, 'cdq '
	jmp	@b

fpuD8	dd	'add ','mul ','com ','comp','sub ','subr','div ','divr'

cD8:
	call	disasm_get_byte
	dec	[disasm_cur_pos]
	push	eax
	shr	al, 3
	and	eax, 7
	mov	byte [edi], 'f'
	inc	edi
	xchg	eax, edx
	mov	eax, [fpuD8+edx*4]
	stosd
	mov	ax, '  '
	stosw
	stosb
	pop	eax
	cmp	dl, 2
	jb	.1
	cmp	dl, 3
	jbe	.2
.1:
	cmp	al, 0xC0
	jb	.2
	mov	eax, 'st0,'
	stosd
	mov	al, ' '
	stosb
.2:
	or	ch, 80h or 20h
	and	ch, not 1
	call	disasm_readrmop
	and	byte [edi], 0
	ret

fpuD9_2:
	dq	'fchs    ','fabs    ',0,0,'ftst    ','fxam    ',0,0
	db	'fld1    fldl2t  fldl2e  fldpi   fldlg2  fldln2  fldz    '
	dq	0
	db	'f2xm1   fyl2x   fptan   fpatan  fxtract fprem1  fdecstp fincstp '
	db	'fprem   fyl2xp1 fsqrt   fsincos frndint fscale  fsin    fcos    '
fpuD9_fnop	db	'fnop    '
cD9:
	call	disasm_get_byte
	sub	al, 0xC0
	jae	.l1
	dec	[disasm_cur_pos]
	shr	al, 3
	and	eax, 7
	cmp	al, 7
	jnz	@f
	mov	eax, 'fnst'
	stosd
	mov	eax, 'cw  '
	jmp	.x1
@@:
	cmp	al, 5
	jnz	@f
	mov	eax, 'fldc'
	stosd
	mov	eax, 'w   '
.x1:
	stosd
	or	ch, 0C1h
	jmp	.cmn
@@:
	mov	edx, 'fld '
	test	al, al
	jz	@f
	mov	edx, 'fst '
	cmp	al, 2
	jz	@f
	mov	edx, 'fstp'
	cmp	al, 3
	jnz	cunk
@@:
	xchg	eax, edx
	stosd
	mov	eax, '    '
	stosd
	or	ch, 80h
	and	ch, not 1
.cmn:
	call	disasm_readrmop
	and	byte [edi], 0
	ret
.l1:
	cmp	al, 10h
	jae	.l2
	mov	edx, 'fld '
	cmp	al, 8
	jb	@f
	mov	edx, 'fxch'
@@:
	xchg	eax, edx
	stosd
	mov	eax, '    '
	stosd
	xchg	eax, edx
	and	al, 7
	add	al, '0'
	shl	eax, 16
	mov	ax, 'st'
	stosd
	clc
	ret
.l2:
	cmp	al, 0x10
	jnz	@f
	mov	esi, fpuD9_fnop
	jmp	.l3
@@:
	sub	al, 0x20
	jb	cerr
	lea	esi, [fpuD9_2+eax*8]
	cmp	byte [esi], 0
	jz	cerr
.l3:
	movsd
	movsd
	and	byte [edi-1], 0
	ret

cDA:
	call	disasm_get_byte
	cmp	al, 0xC0
	jae	cunk
	dec	[disasm_cur_pos]
	shr	al, 3
	and	eax, 7
	mov	word [edi], 'fi'
	inc	edi
	inc	edi
	mov	eax, [fpuD8+eax*4]
	stosd
	mov	ax, '  '
	stosw
	or	ch, 80h
	and	ch, not 1	; 32-bit operand
	call	disasm_readrmop
	and	byte [edi], 0
	ret

fpuDB	dd	'ild ',0,'ist ','istp',0,'ld  ',0,'stp '
cDB:
	call	disasm_get_byte
	cmp	al, 0xC0
	jae	.1
	dec	[disasm_cur_pos]
	shr	al, 3
	and	eax, 7
	xchg	eax, edx
	mov	eax, [fpuDB+edx*4]
	test	eax, eax
	jz	cerr
	mov	byte [edi], 'f'
	inc	edi
	stosd
	mov	ax, '  '
	stosw
	stosb
	or	ch, 80h
	and	ch, not 1	; 32-bit operand
	cmp	dl, 4
	jb	@f
	or	ch, 20h
	and	ch, not 80h	; 80-bit operand
@@:
	call	disasm_readrmop
	and	byte [edi], 0
	ret
.1:
	cmp	al, 0xE3
	jnz	cunk
	mov	eax, 'fnin'
	stosd
	mov	eax, 'it'
	stosd
	dec	edi
	ret		; CF cleared

fpuDC	dd	'add ','mul ',0,0,'subr','sub ','divr','div '
cDC:
	call	disasm_get_byte
	cmp	al, 0xC0
	jae	.1
	dec	[disasm_cur_pos]
	shr	al, 3
	and	eax, 7
	mov	byte [edi], 'f'
	inc	edi
	mov	eax, [fpuD8+eax*4]
	stosd
	mov	ax, '  '
	stosw
	stosb
	or	ch, 0A1h	; qword
	call	disasm_readrmop
	and	byte [edi], 0
	ret
.1:
	mov	dl, al
	shr	al, 3
	and	eax, 7
	mov	eax, [fpuDC+eax*4]
	test	eax, eax
	jz	cerr
	mov	byte [edi], 'f'
	inc	edi
	stosd
	mov	eax, '   s'
	stosd
	mov	al, 't'
	stosb
	and	edx, 7
	lea	eax, [edx+'0']
	stosb
	mov	eax, ', st'
	stosd
	mov	ax, '0'
	stosw
	ret	; CF cleared

fpuDD	dd	'fld ',0,'fst ','fstp',0,0,0,0
fpuDD_2	dq	'ffree   ',0,'fst     ','fstp    ','fucom   ','fucomp  ',0,0
cDD:
	call	disasm_get_byte
	cmp	al, 0xC0
	jae	.1
	dec	[disasm_cur_pos]
	shr	al, 3
	and	eax, 7
	xchg	eax, edx
	mov	eax, [fpuDD+edx*4]
	test	eax, eax
	jz	cunk
	stosd
	mov	eax, '    '
	stosd
	or	ch, 0A1h	; qword operand
	call	disasm_readrmop
	and	byte [edi], 0
	ret
.1:
	push	eax
	shr	al, 3
	and	eax, 7
	xchg	eax, edx
	mov	eax, dword [fpuDD_2+edx*8]
	test	eax, eax
	jz	cerr
	stosd
	mov	eax, dword [fpuDD_2+4+edx*8]
	stosd
	mov	ax, 'st'
	stosw
	pop	eax
	and	al, 7
	add	al, '0'
	stosb
	and	byte [edi], 0
	ret

fpuDE	dd	'add ','mul ',0,0,'subr','sub ','divr','div '
cDE:
	call	disasm_get_byte
	cmp	al, 0xC0
	jae	.1
	dec	[disasm_cur_pos]
	mov	word [edi], 'fi'
	inc	edi
	inc	edi
	shr	al, 3
	and	eax, 7
	mov	eax, [fpuD8+eax*4]
	stosd
	mov	ax, '  '
	stosw
	or	ch, 81h		; force 16-bit
	call	disasm_readrmop
	and	byte [edi], 0
	ret
.1:
	push	eax
	shr	al, 3
	and	eax, 7
	xchg	eax, edx
	mov	eax, [fpuDE+edx*4]
	test	eax, eax
	jz	.fcompp
	mov	byte [edi], 'f'
	inc	edi
	stosd
	mov	al, 'p'
	cmp	byte [edi-1], ' '
	jnz	@f
	mov	byte [edi-1], al
	mov	al, ' '
@@:	stosb
	mov	eax, '  st'
	stosd
	pop	eax
	and	al, 7
	add	al, '0'
	stosb
	mov	ax, ', '
	stosw
	mov	eax, 'st0'
	stosd
	ret	; CF cleared
.fcompp:
	pop	eax
	cmp	al, 0xD9
	jnz	cerr
	mov	eax, 'fcom'
	stosd
	mov	ax, 'pp'
	stosw
	and	byte [edi], 0
	ret

fpuDF	dd	'ild ',0,'ist ','istp','bld ','ild ','bstp','istp'

cDF:
	call	disasm_get_byte
	cmp	al, 0xC0
	jae	.1
	dec	[disasm_cur_pos]
	shr	al, 3
	and	eax, 7
	xchg	eax, edx
	mov	eax, [fpuDF+edx*4]
	test	eax, eax
	jz	cerr
	mov	byte [edi], 'f'
	inc	edi
	stosd
	mov	ax, '  '
	stosw
	stosb
	or	ch, 81h		; force 16-bit operand
	cmp	dl, 4
	jb	@f
	or	ch, 20h
	test	dl, 1
	jnz	@f
	or	ch, 40h
@@:
	call	disasm_readrmop
	and	byte [edi], 0
	ret
.1:
	cmp	al, 0xE0
	jnz	cunk
	mov	eax, 'fnst'
	stosd
	mov	eax, 'sw  '
	stosd
	mov	ax, 'ax'
	stosw
	and	byte [edi], 0
	ret

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; DATA ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

caption_str db 'Kolibri Debugger',0
caption_len = $ - caption_str
begin_str db	'Kolibri Debugger, version 0.2',10
	db	'Hint: type "help" for help, "quit" for quit'
newline	db	10,0
prompt	db	'> ',0

help_groups:
	dd	aControl, 0, 0, help_control_msg
	db	0
	dd	aData, 0, 0, help_data_msg
	db	0
	dd	aBreakpoints, 0, 0, help_breaks_msg
	db	0
; flags field:
; &1: command may be called without parameters
; &2: command may be called with parameters
; &4: command may be called without loaded program
; &8: command may be called with loaded program
commands:
	dd	_aH, OnHelp, HelpSyntax, HelpHelp
	db	0Fh
	dd	aHelp, OnHelp, HelpSyntax, HelpHelp
	db	0Fh
	dd	aQuit, OnQuit, QuitSyntax, QuitHelp
	db	0Dh
	dd	aLoad, OnLoad, LoadSyntax, LoadHelp
	db	6
	dd	aReload, OnReload, ReloadSyntax, ReloadHelp
	db	0Dh
	dd	aTerminate, OnTerminate, TerminateSyntax, TerminateHelp
	db	9
	dd	aDetach, OnDetach, DetachSyntax, DetachHelp
	db	9
	dd	aSuspend, OnSuspend, SuspendSyntax, SuspendHelp
	db	9
	dd	aResume, OnResume, ResumeSyntax, ResumeHelp
	db	0Bh
	dd	aStep, OnStep, StepSyntax, StepHelp
	db	9
	dd	aProceed, OnProceed, ProceedSyntax, ProceedHelp
	db	9
	dd	aCalc, OnCalc, CalcSyntax, CalcHelp
	db	0Eh
	dd	aDump, OnDump, DumpSyntax, DumpHelp
	db	0Bh
	dd	aUnassemble, OnUnassemble, UnassembleSyntax, UnassembleHelp
	db	0Bh
	dd	aBp, OnBp, BpSyntax, BpHelp
	db	0Ah
	dd	aBpm, OnBpmb, BpmSyntax, BpmHelp
	db	0Ah
	dd	aBpmb, OnBpmb, BpmSyntax, BpmHelp
	db	0Ah
	dd	aBpmw, OnBpmw, BpmSyntax, BpmHelp
	db	0Ah
	dd	aBpmd, OnBpmd, BpmSyntax, BpmHelp
	db	0Ah
	dd	aBl, OnBl, BlSyntax, BlHelp
	db	0Bh
	dd	aBc, OnBc, BcSyntax, BcHelp
	db	0Ah
	dd	aBd, OnBd, BdSyntax, BdHelp
	db	0Ah
	dd	aBe, OnBe, BeSyntax, BeHelp
	db	0Ah
	dd	aReg, OnReg, RSyntax, RHelp
	db	0Ah
	dd	aUnpack, OnUnpack, UnpackSyntax, UnpackHelp
	db	9
	dd	0
aHelp	db	5,'help',0
_aH	db	2,'h',0
HelpHelp db	'Help on specified function',10
HelpSyntax db	'Usage: h or help [group | command]',10,0

help_msg db	'List of known command groups:',10
	db	'"help control"     - display list of control commands',10
	db	'"help data"        - display list of commands concerning data',10
	db	'"help breakpoints" - display list of commands concerning breakpoints',10,0
aControl db	8,'control',0
help_control_msg db	'List of control commands:',10
	db	'h = help             - help',10
	db	'quit                 - exit from debugger',10
	db	'load <name> [params] - load program for debugging',10
	db	'reload               - reload debugging program',10
	db	'terminate            - terminate loaded program',10
	db	'detach               - detach from debugging program',10
	db	'stop                 - suspend execution of debugging program',10
	db	'g [<expression>]     - go on (resume execution of debugging program)',10
	db	's = <Ctrl+F7>        - program step',10
	db	'p = <Ctrl+F8>        - program wide step',10
	db	'unpack               - try to bypass unpacker code (heuristic)',10,0
aData	db	5,'data',0
help_data_msg db	'List of data commands:',10
	db	'? <expression>       - calculate value of expression',10
	db	'd [<expression>]     - dump data at given address',10
	db	'u [<expression>]     - unassemble instructions at given address',10
	db	'r <register> <expression> or',10
	db	'r <register>=<expression> - set register value',10,0
aBreakpoints db 12,'breakpoints',0
help_breaks_msg db	'List of breakpoints commands:',10
	db	'bp <expression>      - set breakpoint on execution',10
	db	'bpm[b|w|d] <type> <expression> - set breakpoint on memory access',10
	db	'bl [<number>]        - breakpoint(s) info',10
	db	'bc <number>...       - clear breakpoint',10
	db	'bd <number>...       - disable breakpoint',10
	db	'be <number>...       - enable breakpoint',10,0

aQuit	db	5,'quit',0
QuitHelp db	'Quit from debugger',10
QuitSyntax db	'Usage: quit',10,0

aLoad	db	5,'load',0
LoadHelp db	'Load program for debugging',10
LoadSyntax db	'Usage: load <program-name> [parameters]',10,0

aReload db	7,'reload',0
ReloadHelp db	'Reload debugging program (restart debug session)',10
ReloadSyntax db	'Usage: reload',10,0

aTerminate db	10,'terminate',0
TerminateHelp db 'Terminate debugged program',10
TerminateSyntax db 'Usage: terminate',10,0

aDetach	db	7,'detach',0
DetachHelp db	'Detach from debugged program',10
DetachSyntax db	'Usage: detach',10,0

aSuspend db	5,'stop',0
SuspendHelp db	'Suspend execution of debugged program',10
SuspendSyntax db 'Usage: stop',10,0

aResume db	2,'g',0
ResumeHelp db	'Go (resume execution of debugged program)',10
ResumeSyntax db	'Usage: g',10
	db	'   or: g <expression> - wait until specified address is reached',10,0

aStep	db	2,'s',0
StepHelp db	'Make step in debugged program',10
StepSyntax db	'Usage: s',10,0

aProceed db	2,'p',0
ProceedHelp db	'Make wide step in debugged program (step over CALL, REPxx, LOOP)',10
ProceedSyntax db 'Usage: p',10,0

aDump	db	2,'d',0
DumpHelp db	'Dump data of debugged program',10
DumpSyntax db	'Usage: d <expression> - dump data at specified address',10
	db	'   or: d              - continue current dump',10,0

aCalc	db	2,'?',0
CalcHelp db	'Calculate value of expression',10
CalcSyntax db	'Usage: ? <expression>',10,0

aUnassemble db	2,'u',0
UnassembleHelp db 'Unassemble',10
UnassembleSyntax:
	db	'Usage: u <expression> - unassemble instructions at specified address',10
	db	'   or: u              - continue current unassemble screen',10,0

aReg	db	2,'r',0
RHelp	db	'Set register value',10
RSyntax:
	db	'Usage: r <register> <expression>',10
	db	'   or: r <register>=<expression> - set value of <register> to <expression>',10,0

aBp	db	3,'bp',0
BpHelp	db	'set BreakPoint on execution',10
BpSyntax db	'Usage: bp <expression>',10,0

aBpm	db	4,'bpm',0
aBpmb	db	5,'bpmb',0
aBpmw	db	5,'bpmw',0
aBpmd	db	5,'bpmd',0
BpmHelp	db	'set BreakPoint on Memory access',10
	db	'Maximum 4 breakpoints of this type are allowed',10
	db	'Note that for this breaks debugger is activated after access',10
BpmSyntax db	'Usage: bpmb [w] <expression>',10
	db	'       bpmw [w] <expression>',10
	db	'       bpmd [w] <expression>',10
	db	'       bpm is synonym for bpmd',10
	db	'"w" means break only on writes (default is on read/write)',10,0

aBl	db	3,'bl',0
BlHelp	db	'Breakpoint List',10
BlSyntax db	'Usage: bl          - list all breakpoints',10
	db	'       bl <number> - display info on particular breakpoint',10,0

aBc	db	3,'bc',0
BcHelp	db	'Breakpoint Clear',10
BcSyntax db	'Usage: bc <number-list>',10
	db	'Examples: bc 2',10
	db	'          bc 1 3 4 A',10,0

aBd	db	3,'bd',0
BdHelp	db	'Breakpoint Disable',10
BdSyntax db	'Usage: bd <number-list>',10
	db	'Examples: bd 2',10
	db	'          bd 1 3 4 A',10,0

aBe	db	3,'be',0
BeHelp	db	'Breakpoint Enable',10
BeSyntax db	'Usage: be <number-list>',10
	db	'Examples: be 2',10
	db	'          be 1 3 4 A',10,0

aUnpack	db	7,'unpack',0
UnpackHelp db	'Try to bypass unpacker code',10
UnpackSyntax db	'Usage: unpack',10,0

aUnknownCommand db 'Unknown command',10,0

load_err_msg	db	'Cannot load program. ',0
unk_err_msg	db	'Unknown error code -%4X',10,0
load_err_msgs:
	dd	.1, 0, .3, 0, .5, .6, 0, 0, .9, .A, 0, 0, 0, 0, 0, 0
	dd	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, .1E, .1F, .20
.1		db	'HD undefined.',10,0
.3		db	'Unknown FS.',10,0
.5		db	'File not found.',10,0
.6		db	'Unexpected EOF.',10,0
.9		db	'FAT table corrupted.',10,0
.A		db	'Access denied.',10,0
.1E		db	'No memory.',10,0
.1F		db	'Not Menuet/Kolibri executable.',10,0
.20		db	'Too many processes.',10,0
load_succ_msg	db	'Program loaded successfully! PID=%4X. Use "g" to run.',10,0
need_debuggee	db	'No program loaded. Use "load" command.',10,0
aAlreadyLoaded	db	'Program is already loaded. Use "terminate" or "detach" commands',10,0
terminated_msg	db	'Program terminated.',10,0
aException	db	'Debugged program caused an exception %2X. '
aSuspended	db	'Suspended',10,0
aContinued	db	'Continuing',10,0
aRunningErr	db	'Program is running',10,0
read_mem_err	db	'ERROR: cannot read process memory!!!',10,0
aBreakpointLimitExceeded db 'Breakpoint limit exceeded',10,0
aBreakErr	db	'Cannot activate breakpoint, it will be disabled',10,0
aDuplicateBreakpoint db	'Duplicate breakpoint',10,0
aInvalidBreak	db	'Invalid breakpoint number',10,0
OnBeErrMsg	db	'There is already enabled breakpoint on this address',10,0
aBreakNum	db	'%2X: at %8X',0
aMemBreak1	db	'%2X: on ',0
aMemBreak2	db	'read from ',0
aMemBreak3	db	'access of ',0
aMemBreak4	db	'byte',0
aMemBreak5	db	'word',0
aMemBreak6	db	'dword',0
aMemBreak7	db	' at %8X',0
aOneShot	db	', one-shot',0
aDisabled	db	', disabled',0
aBreakStop	db	'Breakpoint #%2X',10,0
aUserBreak	db	'int3 command at %8X',10,0
;dbgmsg_str	db	'Debug message for process %4X.',10,0
aInvAddr	db	'Invalid address',10,0
NoPrgLoaded_str	db	'No program loaded'
NoPrgLoaded_len = $ - NoPrgLoaded_str
aRunning	db	'Running'
aPaused		db	'Paused'
aPoint		db	0x1C
aMinus		db	'-'
aColon		db	':'
aQuests		db	'??'
aDots		db	'...'
aParseError	db	'Parse error',10,0
aDivByZero	db	'Division by 0',10,0
calc_string	db	'%8X',10,0
aUnaligned	db	'Unaligned address',10,0
aEnabledBreakErr db	'Enabled breakpoints are not allowed',10,0
aInterrupted	db	'Interrupted',10,0
aUnpacked	db	'Unpacked successful!',10,0
aPacked1	db	'Program is probably packed with ',0
aPacked2	db	'.',10,'Try to unpack automatically? [y/n]: ',0
aY_str		db	'y',10,0
aN_str		db	'n',10,0
mxp_nrv_name	db	'mxp_nrv',0
mxp_name	db	'mxp',0
mxp_lzo_name	db	'mxp_lzo',0
mtappack_name	db	'mtappack',0
flags		db	'CPAZSDO'
flags_bits	db	0,2,4,6,7,10,11
regs_strs:
	db	'EAX='
	db	'EBX='
	db	'ECX='
	db	'EDX='
	db	'ESI='
	db	'EDI='
	db	'EBP='
	db	'ESP='
	db	'EIP='
	db	'EFLAGS='

debuggee_pid	dd	0
bSuspended	db	0
bAfterGo	db	0
temp_break	dd	0

disasm_table_1:
	dd	cop22, cop22, cop22, cop22, cop21, cop21, cop0,  cop0		; 0x
	dd	cop22, cop22, cop22, cop22, cop21, cop21, cop0,  cF
	dd	cop22, cop22, cop22, cop22, cop21, cop21, cop0,  cop0		; 1x
	dd	cop22, cop22, cop22, cop22, cop21, cop21, cop0,  cop0
	dd	cop22, cop22, cop22, cop22, cop21, cop21, cseges,cop0		; 2x
	dd	cop22, cop22, cop22, cop22, cop21, cop21, csegcs,cop0
	dd	cop22, cop22, cop22, cop22, cop21, cop21, csegss,cop0		; 3x
	dd	cop22, cop22, cop22, cop22, cop21, cop21, csegds,cop0
	dd	cinc1, cinc1, cinc1, cinc1, cinc1, cinc1, cinc1, cinc1		; 4x
	dd	cdec1, cdec1, cdec1, cdec1, cdec1, cdec1, cdec1, cdec1
	dd	cpush1,cpush1,cpush1,cpush1,cpush1,cpush1,cpush1,cpush1		; 5x
	dd	cpop1, cpop1, cpop1, cpop1, cpop1, cpop1, cpop1, cpop1
	dd	cop0,  cop0,  cunk,  cunk,  csegfs,cseggs,c66,   c67		; 6x
	dd	cpush21,cimul1,cpush22,cimul1,cunk,cunk,  cunk,  cunk
	dd	cjcc1, cjcc1, cjcc1, cjcc1, cjcc1, cjcc1, cjcc1, cjcc1		; 7x
	dd	cjcc1, cjcc1, cjcc1, cjcc1, cjcc1, cjcc1, cjcc1, cjcc1
	dd	cop23, cop23, cop23, cop23, cop22, cop22, cop22, cop22		; 8x
	dd	cop22, cop22, cop22, cop22, cunk,  cop22, cunk,  cpop2
	dd	cop0,  cxchg1,cxchg1,cxchg1,cxchg1,cxchg1,cxchg1,cxchg1		; 9x
	dd	ccbw,  ccwd,  cunk,  cop0,  cop0,  cop0,  cop0,  cop0
	dd	cmov3, cmov3, cmov3, cmov3, cop0,  cop0,  cop0,  cop0		; Ax
	dd	cop21, cop21, cop0,  cop0,  cop0,  cop0,  cop0,  cop0
	dd	cmov11,cmov11,cmov11,cmov11,cmov11,cmov11,cmov11,cmov11		; Bx
	dd	cmov12,cmov12,cmov12,cmov12,cmov12,cmov12,cmov12,cmov12
	dd	cshift1,cshift1,cret2,cop0, cunk,  cunk,  cmov2, cmov2		; Cx
	dd	center,cop0,  cunk,  cunk,  cop0,  cint,  cunk,  cunk
	dd	cshift2,cshift2,cshift3,cshift3,caam,cunk,cunk,  cxlat		; Dx
	dd	cD8,   cD9,   cDA,   cDB,   cDC,   cDD,   cDE,   cDF
	dd	cloopnz,cloopz,cloop,cjcxz, cunk,  cunk,  cunk,  cunk		; Ex
	dd	ccall1,cjmp1, cunk,  cjmp2, cunk,  cunk,  cunk,  cunk
	dd	clock, cunk,  crepnz,crep,  cunk,  cop0,  cop1,  cop1		; Fx
	dd	cop0,  cop0,  cop0,  cop0,  cop0,  cop0,  cop1,  cop1

disasm_table_2:
	dd	cunk,  cunk,  cunk,  cunk,  cunk,  cunk,  cunk,  cunk		; 0x
	dd	cunk,  cunk,  cunk,  cunk,  cunk,  cunk,  cunk,  cunk
	dd	cunk,  cunk,  cunk,  cunk,  cunk,  cunk,  cunk,  cunk		; 1x
	dd	cunk,  cunk,  cunk,  cunk,  cunk,  cunk,  cunk,  cunk
	dd	cunk,  cunk,  cunk,  cunk,  cunk,  cunk,  cunk,  cunk		; 2x
	dd	cunk,  cunk,  cunk,  cunk,  cunk,  cunk,  cunk,  cunk
	dd	cunk,  crdtsc,cunk,  cunk,  csysenter,cunk,cunk, cunk		; 3x
	dd	cunk,  cunk,  cunk,  cunk,  cunk,  cunk,  cunk,  cunk
	dd	cunk,  cunk,  cunk,  cunk,  cunk,  cunk,  cunk,  cunk		; 4x
	dd	cunk,  cunk,  cunk,  cunk,  cunk,  cunk,  cunk,  cunk
	dd	cunk,  cunk,  cunk,  cunk,  cunk,  cunk,  cunk,  cunk		; 5x
	dd	cunk,  cunk,  cunk,  cunk,  cunk,  cunk,  cunk,  cunk
	dd	cunk,  cunk,  cunk,  cunk,  cunk,  cunk,  cunk,  cunk		; 6x
	dd	cunk,  cunk,  cunk,  cunk,  cunk,  cunk,  cunk,  cunk
	dd	cunk,  cunk,  cunk,  cunk,  cunk,  cunk,  cunk,  cunk		; 7x
	dd	cunk,  cunk,  cunk,  cunk,  cunk,  cunk,  cunk,  cunk
	dd	cjcc2, cjcc2, cjcc2, cjcc2, cjcc2, cjcc2, cjcc2, cjcc2		; 8x
	dd	cjcc2, cjcc2, cjcc2, cjcc2, cjcc2, cjcc2, cjcc2, cjcc2
	dd	csetcc,csetcc,csetcc,csetcc,csetcc,csetcc,csetcc,csetcc		; 9x
	dd	csetcc,csetcc,csetcc,csetcc,csetcc,csetcc,csetcc,csetcc
	dd	cunk,  cunk,  ccpuid,cbtx2, cshld, cshld, cunk,  cunk		; Ax
	dd	cunk,  cunk,  cunk,  cbtx2, cshrd, cshrd, cunk,  cop22
	dd	ccmpxchg,ccmpxchg,cunk,cbtx2,cunk, cunk,  cmovzx,cmovzx		; Bx
	dd	cunk,  cunk,  cbtx1, cbtx2, cbsf,  cbsr,  cmovsx,cmovsx
	dd	cunk,  cunk,  cunk,  cunk,  cunk,  cunk,  cunk,  ccmpxchg8b	; Cx
	dd	cbswap,cbswap,cbswap,cbswap,cbswap,cbswap,cbswap,cbswap
	dd	cunk,  cunk,  cunk,  cunk,  cunk,  cunk,  cunk,  cunk		; Dx
	dd	cunk,  cunk,  cunk,  cunk,  cunk,  cunk,  cunk,  cunk
	dd	cunk,  cunk,  cunk,  cunk,  cunk,  cunk,  cunk,  cunk		; Ex
	dd	cunk,  cunk,  cunk,  cunk,  cunk,  cunk,  cunk,  cunk
	dd	cunk,  cunk,  cunk,  cunk,  cunk,  cunk,  cunk,  cunk		; Fx
	dd	cunk,  cunk,  cunk,  cunk,  cunk,  cunk,  cunk,  cunk

reg_table:
	db	2,'al',0
	db	2,'cl',1
	db	2,'dl',2
	db	2,'bl',3
	db	2,'ah',4
	db	2,'ch',5
	db	2,'dh',6
	db	2,'bh',7
	db	2,'ax',8
	db	2,'cx',9
	db	2,'dx',10
	db	2,'bx',11
	db	2,'sp',12
	db	2,'bp',13
	db	2,'si',14
	db	2,'di',15
	db	3,'eax',16
	db	3,'ecx',17
	db	3,'edx',18
	db	3,'ebx',19
	db	3,'esp',20
	db	3,'ebp',21
	db	3,'esi',22
	db	3,'edi',23
	db	3,'eip',24
	db	0

fn70_load_block:
	dd	7
	dd	1
load_params dd	0
	dd	0
	dd	0
i_end:
loadname:
	db	0
	rb	255

prgname_ptr dd ?
prgname_len dd ?

dbgwnd		dd	?

messages	rb	messages_height*messages_width
messages_pos	dd	?

cmdline		rb	cmdline_width+1
cmdline_len	dd	?
cmdline_pos	dd	?
curarg		dd	?

was_temp_break	db	?

dbgbufsize	dd	?
dbgbuflen	dd	?
dbgbuf		rb	256

needzerostart:

context:
_eip	dd	?
_eflags	dd	?
_eax	dd	?
_ecx	dd	?
_edx	dd	?
_ebx	dd	?
_esp	dd	?
_ebp	dd	?
_esi	dd	?
_edi	dd	?

oldcontext rb $-context

dumpread dd	?
dumppos dd	?
dumpdata rb	dump_height*10h

; breakpoint structure:
; dword +0: address
; byte +4: flags
; bit 0: 1 <=> breakpoint valid
; bit 1: 1 <=> breakpoint disabled
; bit 2: 1 <=> one-shot breakpoint
; bit 3: 1 <=> DRx breakpoint
; byte +5: overwritten byte
;          for DRx breaks: flags + (index shl 6)
breakpoints_n = 256
breakpoints	rb	breakpoints_n*6
drx_break	rd	4

disasm_buf_size		dd	?

bReload			db	?

needzeroend:

disasm_buffer		rb	256
disasm_start_pos	dd	?
disasm_cur_pos		dd	?
disasm_cur_str		dd	?
disasm_string		rb	256

i_param		rb	256

; stack
	align	400h
	rb	400h
used_mem: