You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

MASM32中push hInstance与pop wc.hInstance指令作用及替代方案问询

关于Win32汇编中push hInstance/pop wc.hInstance指令的解释

问题描述

这是我在网上找到的一个基础Win32程序,目前我理解大部分内容,但无法理解以下两行指令的作用:

push  hInstance
pop   wc.hInstance

希望有人能解释它们的功能,以及是否存在其他指令可以实现相同的操作。我曾通过谷歌和相关文档了解push、pop指令的基本作用,但无法将其与该程序的上下文结合起来理解。

完整程序代码

.386
.model flat,stdcall
option casemap:none
include \masm32\include\windows.inc
include \masm32\include\user32.inc
includelib \masm32\lib\user32.lib            ; calls to functions in user32.lib and kernel32.lib
include \masm32\include\kernel32.inc
includelib \masm32\lib\kernel32.lib
WinMain proto :DWORD,:DWORD,:DWORD,:DWORD

.DATA                     ; initialized data
ClassName db "SimpleWinClass",0        ; the name of our window class
AppName db "Our First Window",0        ; the name of our window

.DATA?                ; Uninitialized data
hInstance HINSTANCE ?        ; Instance handle of our program
CommandLine LPSTR ?
.CODE                ; Here begins our code
start:
invoke GetModuleHandle, NULL            ; get the instance handle of our program.
                                                                       ; Under Win32, hmodule==hinstance mov hInstance,eax
mov hInstance,eax
invoke GetCommandLine                        ; get the command line. You don't have to call this function IF
                                                                       ; your program doesn't process the command line.
mov CommandLine,eax
invoke WinMain, hInstance,NULL,CommandLine, SW_SHOWDEFAULT        ; call the main function
invoke ExitProcess, eax                           ; quit our program. The exit code is returned in eax from WinMain.

WinMain proc hInst:HINSTANCE,hPrevInst:HINSTANCE,CmdLine:LPSTR,CmdShow:DWORD
    LOCAL wc:WNDCLASSEX                                            ; create local variables on stack
    LOCAL msg:MSG
    LOCAL hwnd:HWND

    mov   wc.cbSize,SIZEOF WNDCLASSEX                   ; fill values in members of wc
    mov   wc.style, CS_HREDRAW or CS_VREDRAW
    mov   wc.lpfnWndProc, OFFSET WndProc
    mov   wc.cbClsExtra,NULL
    mov   wc.cbWndExtra,NULL
    push  hInstance
    pop   wc.hInstance
    mov   wc.hbrBackground,COLOR_WINDOW+1
    mov   wc.lpszMenuName,NULL
    mov   wc.lpszClassName,OFFSET ClassName
    invoke LoadIcon,NULL,IDI_APPLICATION
    mov   wc.hIcon,eax
    mov   wc.hIconSm,eax
    invoke LoadCursor,NULL,IDC_ARROW
    mov   wc.hCursor,eax
    invoke RegisterClassEx, addr wc                       ; register our window class
    invoke CreateWindowEx,NULL,\
                ADDR ClassName,\
                ADDR AppName,\
                WS_OVERLAPPEDWINDOW,\
                CW_USEDEFAULT,\
                CW_USEDEFAULT,\
                CW_USEDEFAULT,\
                CW_USEDEFAULT,\
                NULL,\
                NULL,\
                hInst,\
                NULL
    mov   hwnd,eax
    invoke ShowWindow, hwnd,CmdShow               ; display our window on desktop
    invoke UpdateWindow, hwnd                                 ; refresh the client area

    .WHILE TRUE                                                         ; Enter message loop
                invoke GetMessage, ADDR msg,NULL,0,0
                .BREAK .IF (!eax)
                invoke TranslateMessage, ADDR msg
                invoke DispatchMessage, ADDR msg
   .ENDW
    mov     eax,msg.wParam                                            ; return exit code in eax
    ret
WinMain endp

WndProc proc hWnd:HWND, uMsg:UINT, wParam:WPARAM, lParam:LPARAM
    .IF uMsg==WM_DESTROY                           ; if the user closes our window
        invoke PostQuitMessage,NULL             ; quit our application
    .ELSE
        invoke DefWindowProc,hWnd,uMsg,wParam,lParam     ; Default message processing
        ret
    .ENDIF
    xor eax,eax
    ret
WndProc endp

end start

指令功能与等价实现

功能解释

这两行指令的核心是把全局变量hInstance的值赋值给WNDCLASSEX结构体实例wc的hInstance成员。

x86汇编的mov指令不支持直接的内存到内存数据传输(不能直接写mov wc.hInstance, hInstance),必须借助寄存器中转。而push+pop的组合是另一种实现方式:

  1. push hInstance:将全局变量hInstance中的值压入栈内存
  2. pop wc.hInstance:把栈顶的值弹出,写入到wc.hInstance对应的内存地址中

等价实现方式

有几种更直观的写法,效果完全一致:

  • 寄存器中转写法(最常用):
    mov eax, hInstance
    mov wc.hInstance, eax
    
  • MASM伪指令简化:
    MASM汇编器支持直接写mov wc.hInstance, hInstance,它会自动在编译时转换成寄存器中转的指令,本质和上面的写法相同。

上下文意义

在Win32窗口程序中,WNDCLASSEX的hInstance成员必须设置为当前程序的实例句柄,用来将窗口类与当前进程绑定。这里的hInstance是程序启动时通过GetModuleHandle获取的全局实例句柄,赋值给结构体后,才能通过RegisterClassEx成功注册窗口类,为后续创建窗口做准备。


内容的提问来源于stack exchange,提问作者Mohamed Tarek

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.06 06:55:54