首页
社区
课程
招聘
[求助]DialogBoxParam 函数遇到的死循环
发表于: 2008-4-19 00:09 5186

[求助]DialogBoxParam 函数遇到的死循环

2008-4-19 00:09
5186
在看罗叔的win32汇编中子类化与超类化这一章时,我写的代码。
DialogBoxParam函数调用后,只显示出两个Edit控件,看不见窗口。
CPU占用98%,应该是有死循环。
我找啊找啊找。。。。怎么就找不到呢??
各位高手帮忙看看

代码:
		.386
		.model	flat, stdcall
		option	casemap:none
		
include		windows.inc
include		kernel32.inc
includelib	kernel32.lib
include		user32.inc
includelib	user32.lib

IDD_DLG1	equ	1000
IDC_EDIT1 	equ	1001
IDC_EDIT2 	equ	1002

		.data
szSuperEdit	db	'SuperEdit',0
szEdit		db	'Edit',0
szAllowedChar	db	'0123456789abcdefABCDEF',0

		.data?
hInstance	dd	?
_EditProc	dd	?

		.code
_SuperClass	proto		
_SuperEditProc	proto	:DWORD, :DWORD, :DWORD, :DWORD
_DlgProc	proto	:DWORD, :DWORD, :DWORD, :DWORD

_WinMain	proc
		invoke	GetModuleHandle,0
		mov	hInstance, eax
		invoke	_SuperClass
		
		invoke	DialogBoxParam, hInstance, IDD_DLG1, NULL, offset _DlgProc, NULL
		invoke	ExitProcess,0
		ret

_WinMain 	endp

_DlgProc	proc	uses ebx eax edi esi hDlg, uMsg, wParam, lParam
		mov	eax, uMsg
		
		.if	eax == WM_CLOSE
			invoke	EndDialog, hDlg, 0
		.else
			mov	eax, FALSE
			ret
		.endif
		mov	eax, TRUE
		ret

_DlgProc 	endp

_SuperClass	proc
		LOCAL	@WndClass:WNDCLASSEX
		
		invoke	RtlZeroMemory,addr @WndClass, sizeof @WndClass
		
		mov	@WndClass.cbSize, sizeof @WndClass
		invoke	GetClassInfoEx, NULL, offset szEdit, addr @WndClass
		push	@WndClass.lpfnWndProc
		pop	_EditProc
		mov	@WndClass.lpfnWndProc, offset _SuperEditProc
		mov	@WndClass.lpszClassName, offset szSuperEdit
		push	hInstance
		pop	@WndClass.hInstance
		
		
		invoke	RegisterClassEx, addr @WndClass
	
		ret

_SuperClass 	endp

_SuperEditProc	proc uses ebx esi edi hEdit, uMsg, wParam, lParam
		mov	eax, uMsg
		
		.if	eax == WM_CHAR
			mov	eax, wParam
			mov	edi, offset szAllowedChar
			mov	ecx, sizeof szAllowedChar
			repnz	scasb
			
			.if	ZERO?
				cmp	eax, '9'
				jna	@F
				and	al, not 20H
				@@:
				mov	wParam, eax
			.else
				xor	eax,eax
				ret
			.endif
		.endif
		
		invoke	CallWindowProc, _EditProc, hEdit, uMsg, wParam, lParam
		ret

_SuperEditProc endp

end		_WinMain


资源:
#include	"C:\RadASM\masm32\include\resource.h"

#define 	IDD_DLG1	1000
#define	 	IDC_EDIT1 	1001
#define 	IDC_EDIT2 	1002
IDD_DLG1 DIALOG 6,6,194,106
CAPTION "ClassModify"
STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU
FONT 9, "宋体"
{
  CONTROL "",IDC_EDIT1,"Edit",0x50010000,28,16,144,19,0x00000200
  CONTROL "",IDC_EDIT2,"SuperEdit",0x50010000,26,53,146,19,0x00000200
}


[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课

收藏
免费 0
支持
分享
最新回复 (1)
雪    币: 722
活跃值: (123)
能力值: ( LV12,RANK:300 )
在线值:
发帖
回帖
粉丝
2
_DlgProc  proc  uses ebx eax edi esi hDlg, uMsg, wParam, lParam
    mov  eax, uMsg
   
    .if  eax == WM_CLOSE
      invoke  EndDialog, hDlg, 0
    .else
      mov  eax, FALSE
      ret
    .endif
    mov  eax, TRUE
    ret

_DlgProc   endp

你的消息处理函数这么写,当然不行了:
1. 只对WM_CLOSE做出响应,对其他消息不做出响应,那连窗口都没有成功创建呢(如没有响应WM_PAINT,所以窗口根本没有画出来!)
在其他情况下应该调用DefWindowProc处理

2. 你的uses里面加入了eax,这是错的。这样生成的代码会是这样:

push ebp
mov ebp,esp
push ebx
push eax;eax先入栈保存了
……
到了ret之前:
pop eax;eax的值又弹回来了
pop ebx
leave
ret

这样在返回时,eax的值不是由你的操作代码决定的(也就是说你在最后mov eax,FALSE还是mov eax,TRUE都没有意义),而是永远和函数被调用时传入的eax一样,这当然是不对的。eax是用来保存函数调用的返回值的,它不能包括在uses里,也不需要包括在uses里(包括在uses里的目的,是保证调用函数后这个寄存器值不变,而eax本来就是用来保存函数返回值的,这个值本来就是要变的)。
2008-4-19 17:48
0
游客
登录 | 注册 方可回帖
返回