Winapi Win32程序集-WNDCLASSEX.lpfnWndProc是否应为_cdecl?

Winapi Win32程序集-WNDCLASSEX.lpfnWndProc是否应为_cdecl?,winapi,assembly,Winapi,Assembly,我已经设法在纯汇编中编写了一个简单的Windows消息循环。有一件事让我在去那里的路上有点头疼,现在我想知道为什么会这样 这是我的WndProc函数(我在WNDCLASSEX.lpfnWndProc中指定的函数): 我觉得有点奇怪的是,我不应该清理WndProc中的堆栈参数。上面发布的代码有效,但如果我尝试做我认为应该做的事情,则如下所示: CMP DWORD [EBP+12d],WM_CLOSE ;switch msg (UINT, second param) JNZ eval_wm_

我已经设法在纯汇编中编写了一个简单的Windows消息循环。有一件事让我在去那里的路上有点头疼,现在我想知道为什么会这样

这是我的WndProc函数(我在WNDCLASSEX.lpfnWndProc中指定的函数):


我觉得有点奇怪的是,我不应该清理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


是这样吗?

WndProc应该使用
WINAPI
,即
stdcall
——也就是说,函数本身应该清除任何参数


它对您有效的原因可能是调用作用域不依赖于ESP在调用后处于正确的位置,并且当它本身返回时,当ESP使用EBP中条目中保存的值重新初始化时,堆栈被“修复”。

好的,但是,我尝试清理(添加ESP,16d)也应该没有效果,但如前所述,它会使程序崩溃。可能是您的
POP EBP
导致了该问题。好吧,运行的版本(第一个)中确实包含
POP EBP
。在任何情况下,WndProc之后清理的正确方法是在其中执行
ret 16
。Win32 API中的所有内容,除了
wsprintf()
,都包含在内,使用
\uuu stdcall
,自Microsoft在Windows 95中迁移到32位后一直如此。回到16位时代,一切都是
\uu cdecl
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