Win32程序集 - WNDCLASSEX.lpfnWndProc应该是_cdecl吗?

时间:2014-09-24 17:31:01

标签: winapi assembly

我设法在纯汇编中编写一个简单的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?

是这样的吗?

1 个答案:

答案 0 :(得分:1)

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

它无论如何都适用于你的原因可能是调用范围不依赖于ESP在调用之后的正确位置,当它自身返回堆栈时,当使用保存的值重新初始化ESP时,它被“修复”进入EBP。