从 x64 程序集调用 CreateWindowEx

问题描述 投票:0回答:1

我正在尝试在 NASM 中创建一个窗口,但在调用 CreateWindowExW 时遇到问题。似乎接收到了错误的参数。

这是

window.asm

的(相关)代码
SetupWindow:
; Stack setup
        push rbp
        mov rbp, rsp

        push r12
        push r13

; Variables
        sub rsp, sizeof(WNDCLASSEXW)

; Clear WNDCLASSEXW
        cld
        mov r12, rsp
        mov rdi, r12
        xor eax, eax
        mov ecx, sizeof(WNDCLASSEXW)
        rep stosb

; Set WNDCLASSEXW fields
        mov r13, sizeof(WNDCLASSEXW)    ; sizeof(WNDCLASSEXW) -> cbSize
        mov dword [r12 + WNDCLASSEXW.cbSize], r13d
        lea r13, [rel WindowProcedure]  ; WindowProcedure -> lpfnWndProc
        mov qword [r12 + WNDCLASSEXW.lpfnWndProc], r13
        lea r13, [rel className]        ; className -> lpszClassName
        mov qword [r12 + WNDCLASSEXW.lpszClassName], r13

; GetModuleHandleA(NULL) -> hInstance
        sub rsp, 32
        xor eax, eax
        call GetModuleHandleA
        add rsp, 32
        mov qword [r12 + WNDCLASSEXW.hInstance], rax

; RegisterClassExW
        sub rsp, 32                     ; Shadow space
        mov rcx, r12                    ; Window class structure
        call RegisterClassExW
        add rsp, 32                     ; Clear shadow space

; CreateWindowExW
        sub rsp, 80
        xor ecx, ecx                    ; No extended styles
        mov rdx, qword [r12 + WNDCLASSEXW.lpszClassName]
        lea r8, [rel windowName]        ; Window name
        mov r9, WS_OVERLAPPEDWINDOW     ; Generic window style
        mov r13, CW_USEDEFAULT          ; CW_USEDEFAULT for X, Y, nWidth, nHeight
        mov qword [rsp + 32 + 0], r13   ; X
        mov qword [rsp + 32 + 8], r13   ; Y
        mov qword [rsp + 32 + 16], r13  ; nWidth
        mov qword [rsp + 32 + 24], r13  ; nHeight
        mov qword [rsp + 32 + 32], rcx  ; hWndParent
        mov qword [rsp + 32 + 40], rcx  ; hMenu
        mov r13, qword [r12 + WNDCLASSEXW.hInstance]
        mov qword [rsp + 32 + 48], r13  ; hInstance
        mov qword [rsp + 32 + 56], rcx  ; lpParam
        call CreateWindowExW2
        add rsp, 80

; Check window
        cmp rax, 0
        jne .success

.error:
        sub rsp, 32
        call GetLastError
        add rsp, 32
        mov ecx, eax
        call ExitProcess
.success:
        mov [rel window], rax
        mov rcx, [rel window]
        mov edx, SW_SHOWNORMAL
        call ShowWindow

这是

win32.inc
的代码:

; kernel32
        extern ExitProcess
        extern GetLastError
        extern GetModuleHandleA

; user32
        extern CreateWindowExW
        extern RegisterClassExW
        extern ShowWindow

        struc WNDCLASSEXW
            .cbSize: resd 1
            .style: resd 1
            .lpfnWndProc: resq 1
            .cbClsExtra: resd 1
            .cbWndExtra: resd 1
            .hInstance: resq 1
            .hIcon: resq 1
            .hCursor: resq 1
            .hbrBackground: resq 1
            .lpszMenuName: resq 1
            .lpszClassName: resq 1
            .hIconSm: resq 1
        endstruc

        %define CW_USEDEFAULT 80000000h

        %define SW_SHOWNORMAL 1

        %define WS_CAPTION 00C00000h
        %define WS_MAXIMIZEBOX 00010000h
        %define WS_MINIMIZEBOX 00020000h
        %define WS_OVERLAPPED 00000000h
        %define WS_SYSMENU 00080000h
        %define WS_THICKFRAME 00040000h

        %define WS_OVERLAPPEDWINDOW (WS_CAPTION | WS_MAXIMIZEBOX | WS_MINIMIZEBOX | \
                WS_OVERLAPPED | WS_SYSMENU | WS_THICKFRAME)

完整代码位于 GitHub 上:https://github.com/MobSlicer152/pong

winapi x86-64 nasm win64
1个回答
0
投票

我知道我做错了什么了。基本上,我认为在四个寄存器参数之后,它与X86调用约定相同。然而,事实并非如此。整数参数按从左到右的顺序排列,并填充为 8 个字节。进行此更改似乎解决了我遇到的问题。

但是,函数开始返回

NULL
,但 GetLastError 将返回 0 (
ERROR_SUCCESS
)。

我解决了这个问题。我意识到如果窗口过程返回 false,CreateWindow 就会失败。我改成return true,现在就成功了

© www.soinside.com 2019 - 2024. All rights reserved.