
; StackEdit Version 1.0
; Copyright © Tommy Lillehagen, 2003.
; All rights reserved.

format PE GUI 4.0
entry start

include '%fasminc%\win32a.inc'

section '.data' data readable writeable

  _class	db 'STACKED32',0
  _fontname	db 'Terminal',0
  _stack0	db 'Stack pointer'
  _stack0.size	= $ - _stack0

  hinstance	dd ?
  wc		WNDCLASS

section '.code' code readable executable

  start:
	invoke	GetModuleHandle,0
	mov	[hinstance],eax

	mov	[wc.hInstance],eax
	mov	[wc.style],CS_GLOBALCLASS+CS_DBLCLKS
	mov	[wc.lpfnWndProc],StackEd
	xor	eax,eax
	mov	[wc.cbClsExtra],eax
	mov	[wc.cbWndExtra],eax
	mov	[wc.lpszMenuName],eax
	invoke	LoadCursor,0,IDC_ARROW
	mov	[wc.hCursor],eax
	mov	[wc.hbrBackground],COLOR_WINDOW+1
	mov	[wc.lpszClassName],_class
	invoke	RegisterClass,wc
	or	eax,eax
	jz	app_end

	invoke	DialogBoxParam,[hinstance],37,0,MainDlg,0

  app_end:
	invoke	ExitProcess,0

proc MainDlg, hdlg,wmsg,wparam,lparam
	enter
	push	ebx esi edi
	cmp	[wmsg],WM_CLOSE
	je	.wmclose
	xor	eax,eax
	jmp	.finish
  .wmclose:
	invoke	EndDialog,[hdlg],0
  .processed:
	mov	eax,1
  .finish:
	pop	edi esi ebx
	return
	endp

; Function:     StackEd
; Description:  Callback procedure for the StackEd32 control
; Author:       Tommy Lillehagen

proc StackEd, hwnd,msg,wparam,lparam

  .rc	      RECT
  .pt	      POINT
  .ps	      PAINTSTRUCT
  .buffer     rb 8
  .hfont      dd ?
  .hpen       dd ?
  .lebp       dd ?
  .lesp       dd ?
  .lstart     dd ?

	enter
	push	ebx esi edi
	cmp	[msg],WM_CREATE
	je	.create
	cmp	[msg],WM_DESTROY
	je	.destroy
	cmp	[msg],WM_PAINT
	je	.paint
  .defwndproc:
	invoke	DefWindowProc,[hwnd],[msg],[wparam],[lparam]
	jmp	.finish
  .create:
	xor	eax,eax
	jmp	.finish
  .destroy:
	xor	eax,eax
	jmp	.finish
  .paint:
	mov	[.lstart],esp
	sub	[.lstart],12
	mov	[.lesp],esp
	mov	[.lebp],ebp

	lea	eax,[.ps]
	invoke	BeginPaint,[hwnd],eax
	mov	ebx,eax

	lea	eax,[.rc]
	invoke	GetClientRect,[hwnd],eax

	invoke	GetSysColor,COLOR_BTNFACE
	invoke	CreatePen,PS_SOLID,1,eax
	mov	[.hpen],eax

	invoke	SelectObject,ebx,[.hpen]

	lea	eax,[.pt]
	invoke	MoveToEx,ebx,54,[.rc.top],eax
	invoke	LineTo,ebx,54,[.rc.bottom]

	lea	eax,[.pt]
	invoke	MoveToEx,ebx,98,[.rc.top],eax
	invoke	LineTo,ebx,98,[.rc.bottom]

	lea	eax,[.pt]
	invoke	MoveToEx,ebx,142,[.rc.top],eax
	invoke	LineTo,ebx,142,[.rc.bottom]

	lea	eax,[.pt]
	invoke	MoveToEx,ebx,198,[.rc.top],eax
	invoke	LineTo,ebx,198,[.rc.bottom]

	invoke	CreateFont,-8,0,0,0,0,0,0,0,DEFAULT_CHARSET,0,0,DEFAULT_QUALITY,0,_fontname
	mov	[.hfont],eax

	invoke	SelectObject,ebx,[.hfont]

	invoke	GetSysColor,COLOR_BTNSHADOW
	invoke	SetTextColor,ebx,eax

	mov	eax,[.rc.bottom]
	sub	eax,[.rc.top]
	mov	ecx,10
	xor	edx,edx
	div	ecx
	mov	ecx,eax
	inc	ecx

	mov	edx,2
	mov	esi,[.lstart]

    .paint_loop:

	mov	eax,esi
	lea	edi,[.buffer]
	call	DWord2Hex

	push	ecx edx
	invoke	TextOut,ebx,2,edx,edi,8
	pop	edx ecx

	lea	edi,[.buffer]
	mov	dword [edi],'ESP'
	add	edi,3
	mov	eax,esi
	sub	eax,[.lesp]
	test	eax,eax
	jnz	.not_stackpointer

	push	eax ecx edx
	invoke	TextOut,ebx,200,edx,_stack0,_stack0.size
	pop	edx ecx eax

      .not_stackpointer:
	call	Byte2Hex

	lea	edi,[.buffer]

	push	ecx edx
	invoke	TextOut,ebx,58,edx,edi,6
	pop	edx ecx

	lea	edi,[.buffer]
	mov	dword [edi],'EBP'
	add	edi,3
	mov	eax,esi
	sub	eax,[.lebp]
	call	Byte2Hex

	lea	edi,[.buffer]

	push	ecx edx
	invoke	TextOut,ebx,102,edx,edi,6
	pop	edx ecx

	mov	eax,[esi]
	lea	edi,[.buffer]
	call	DWord2Hex

	push	ecx edx
	invoke	TextOut,ebx,146,edx,edi,8
	pop	edx ecx

	add	edx,10
	add	esi,4

	dec	ecx
	test	ecx,ecx
	jnz    .paint_loop

	invoke	DeleteObject,[.hfont]
	invoke	DeleteObject,[.hpen]

	lea	eax,[.ps]
	invoke	EndPaint,[hwnd],eax

	xor	eax,eax
	jmp	.finish
  .finish:
	pop	edi esi ebx
	return
	endp

; Function:     Byte2Hex
; Description:  Convert an integer to a hexadecimal string
; Parameters:   AL:  Byte to be converted
;               EDI: Pointer to buffer where to place the result
; Return:       Nothing
; Author:       Tommy Lillehagen

Byte2Hex:
	push	edx
	test	eax,eax
	jns	.nsgn
	mov	byte [edi],'-'
	inc	edi
	neg	al
	jmp	.cnv
    .nsgn:
	mov	byte [edi],'+'
	inc	edi
    .cnv:
	mov	dl,al
	mov	dh,al
	shr	dl,4
	and	dh,0Fh
	add	dx,3030h
	cmp	dl,'9'
	jle	.lok
	add	dl,7
    .lok:
	cmp	dh,'9'
	jle	.hok
	add	dh,7
    .hok:
	mov	word [edi],dx
	pop	edx
	ret

; Function:     DWord2Hex
; Description:  Convert an integer to a hexadecimal string
; Parameters:   EAX: Double word to be converted
;               EDI: Pointer to buffer where to place the result
; Return:       Nothing
; Author:       Tommy Lillehagen

DWord2Hex:
	push	ebx ecx edx edi
	mov	ebx,16
	xor	ecx,ecx
      .new:
	xor	edx,edx
	div	ebx
	push	edx
	inc	ecx
	test	eax,eax
	jnz	.new
	mov	ebx,ecx
	mov	ecx,8
      .loop:
	cmp	ecx,ebx
	jle	.get_digit
	mov	al,0
	jmp	.cnv
      .get_digit:
	pop	eax
      .cnv:
	add	al,30h
	cmp	al,'9'
	jng	.ok
	add	al,7
      .ok:
	stosb
	loop	.loop
	pop	edi edx ecx ebx
	ret

section '.rsrc' resource data readable

  directory RT_DIALOG,dialogs

  resource dialogs,\
	   37,LANG_ENGLISH+SUBLANG_DEFAULT,maindlg

  dialog maindlg,'Stack Edit',100,100,250,70,WS_CAPTION+WS_POPUP+WS_SYSMENU+DS_MODALFRAME
    dialogitem 'STACKED32','',101,4,4,242,62,WS_VISIBLE+WS_BORDER
  enddialog

section '.idata' import data readable writeable

  library  kernel32,'KERNEL32.DLL',\
	   user32,'USER32.DLL',\
	   gdi32,'GDI32.DLL'

  include '%fasminc%/apia/kernel32.inc'
  include '%fasminc%/apia/user32.inc'
  include '%fasminc%/apia/gdi32.inc'