2

我是 Win32 程序集的新手:

我学习这个程序的代码,它的窗口很简单。但我得到了错误:

错误 a2070 无效指令操作数 (MASM)

我在谷歌上搜索过这个错误,但我仍然不明白。

.386
.model flat, stdcall
option casemap:none

include \masm32\include\windows.inc
include \masm32\include\kernel32.inc
include \masm32\include\user32.inc
includelib \masm32\lib\kernel32.lib
includelib \masm32\lib\user32.lib

WinMain PROTO :HINSTANCE, :HINSTANCE, :LPSTR, :DWORD

.data
    AppName     db "First Windows", 0
    ClassName   db "Window Class", 0

.data?
    hInstance   dd ?
    CommandLine dd ?

.code
start:
    invoke  GetModuleHandle, NULL
    MOV     hInstance, EAX
    invoke  GetCommandLine
    MOV     CommandLine, EAX
    invoke  WinMain, hInstance, NULL, CommandLine, SW_SHOWDEFAULT
    invoke  ExitProcess, EAX

    WinMain PROC ahInstance:HINSTANCE, \
            ahPrevInstance:HINSTANCE, \
            aCommandLine:LPSTR, \
            aCommandShow:DWORD
        LOCAL   wc:WNDCLASSEX
        LOCAL   hwnd:HANDLE
        LOCAL   msg:MSG

        MOV     wc.cbSize, SIZEOF WNDCLASSEX
        MOV     wc.style, CS_HREDRAW or CS_VREDRAW
        MOV     wc.lpfnWndProc, offset WndProc
        MOV     wc.cbClsExtra, NULL
        MOV     wc.cbWndExtra, NULL
        MOV     wc.hInstance, hInstance ;;;;;;;;;;;;;;;; Error here

        invoke  LoadIcon, NULL, IDI_APPLICATION
        MOV     wc.hIcon, EAX
        MOV     wc.hIconSm, EAX
        invoke  LoadCursor, NULL, IDC_ARROW
        MOV     wc.hCursor, EAX
        MOV     wc.hbrBackground, COLOR_WINDOW+1
        MOV     wc.lpszMenuName, NULL
        MOV     wc.lpszClassName, offset ClassName

        invoke  RegisterClassEx, addr wc

        invoke  CreateWindowEx, NULL, addr ClassName, addr AppName, \
                WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, \
                CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, ahInstance, NULL
        MOV     hwnd, EAX

        invoke  ShowWindow, hwnd, SW_SHOWNORMAL
        invoke  UpdateWindow, hwnd

        .WHILE TRUE
            invoke  GetMessage, addr msg, NULL, 0, 0
            .BREAK .IF (!EAX)
            invoke  TranslateMessage, addr msg
            invoke  DispatchMessage, addr msg
        .ENDW

        MOV EAX, msg.wParam
        RET
    WinMain endp

    WndProc PROC ahWnd:HWND, aMsg:DWORD, awParam:WPARAM, alParam:LPARAM
        .IF aMsg == WM_DESTROY
            invoke  PostQuitMessage, NULL
        .ELSE
            invoke  DefWindowProc, ahWnd, aMsg, awParam, alParam
            ret
        .ENDIF
        XOR EAX, EAX
        ret
    WndProc endp
end start

那行:

MOV     wc.hInstance, hInstance

得到一个错误,我替换为:

PUSH hInstance
POP  wc.hInstance

--> 这没问题。

但我不明白为什么?

任何人都可以帮助我。

4

1 回答 1

2

wc.hInstance指的是 的一部分wc,它在堆栈上,因此在内存中。hInstance也在堆栈上,因此在内存中。如果您尝试任何内存到内存的移动,您会发现它不起作用:

mov [esp], [ebp]
error: invalid operand.

这只是 x86 指令集的限制;x86 指令集没有内存到内存的移动。你必须把它变成两个指令,就像你用pushand做的那样pop

于 2013-10-08T03:51:35.127 回答