我设法在纯汇编中编写一个简单的Windows消息循环。有一件事让我在那里的路上有点头疼,现在我想知道为什么会这样。
这是我的WndProc函数(我在WNDCLASSEX.lpfnWndProc中指定的函数):
_WndProc: ;LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
PUSH EBP
MOV EBP,ESP
CMP DWORD [EBP+12d],WM_CLOSE ;switch msg (UINT, second param)
JNZ eval_wm_destroy
PUSH DWORD [EBP+8d]
CALL _DestroyWindow@4
POP EBP
RET
eval_wm_destroy:
CMP DWORD [EBP+12d],WM_DESTROY
JNZ default_behavior
PUSH 0
CALL _PostQuitMessage@4
POP EBP
RET
default_behavior:
PUSH DWORD [EBP+20]
PUSH DWORD [EBP+16]
PUSH DWORD [EBP+12]
PUSH DWORD [EBP+8]
CALL _DefWindowProcA@16
POP EBP
RET
;---
我觉得有点奇怪的是我不应该清理WndProc中的堆栈参数。上面发布的代码有效,而如果我尝试做我认为应该做的事情,就像这样:
CMP DWORD [EBP+12d],WM_CLOSE ;switch msg (UINT, second param)
JNZ eval_wm_destroy
PUSH DWORD [EBP+8d]
CALL _DestroyWindow@4
POP EBP
ADD ESP,16d
RET
我遇到了崩溃。这种行为表明窗口过程不应该自行清理,使其成为... _cdecl?
是这样的吗?
答案 0 :(得分:1)
WndProc应该使用WINAPI
,即stdcall
- 也就是说,函数本身应该清理任何参数。
它无论如何都适用于你的原因可能是调用范围不依赖于ESP在调用之后的正确位置,当它自身返回堆栈时,当使用保存的值重新初始化ESP时,它被“修复”进入EBP。