Winapi Win32程序集-WNDCLASSEX.lpfnWndProc是否应为_cdecl?
我已经设法在纯汇编中编写了一个简单的Windows消息循环。有一件事让我在去那里的路上有点头疼,现在我想知道为什么会这样 这是我的WndProc函数(我在WNDCLASSEX.lpfnWndProc中指定的函数):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_
我觉得有点奇怪的是,我不应该清理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