我正在尝试在 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
我知道我做错了什么了。基本上,我认为在四个寄存器参数之后,它与X86调用约定相同。然而,事实并非如此。整数参数按从左到右的顺序排列,并填充为 8 个字节。进行此更改似乎解决了我遇到的问题。
但是,函数开始返回
NULL
,但 GetLastError 将返回 0 (ERROR_SUCCESS
)。
我解决了这个问题。我意识到如果窗口过程返回 false,CreateWindow 就会失败。我改成return true,现在就成功了