Вызов CreateWindowEx из сборки x64

Я пытаюсь создать окно в 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

Ваш вопрос кажется довольно хорошим, но люди ценят «минимальный, воспроизводимый пример», для которого требуются полные исходные коды программы, а также команды, которые вы используете для сборки программы. См. stackoverflow.com/help/minimal-reproducible-example

ecm 17.03.2024 21:00

RCX, RDX, R8 и R9 присваиваются 0, класс окна, заголовок окна и стиль.

mobslicer152 18.03.2024 01:07

Я понял, что у меня порядок наоборот, и я не включил теневое пространство в смещения. Однако теперь CreateWindowExW возвращает NULL, а GetLastError возвращает 0.

mobslicer152 18.03.2024 01:18
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
3
109
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Я понял, что я сделал не так. По сути, я думал, что после четырех параметров регистра это то же самое, что и соглашение о вызовах X86. Однако это не так. Целочисленные параметры идут в порядке слева направо и дополняются до 8 байт. Кажется, что внесение этого изменения решило мою проблему.

Однако затем функция начала возвращать NULL, но GetLastError возвращала 0 (ERROR_SUCCESS).

Я решил это. Я понял, что CreateWindow терпит неудачу, если оконная процедура возвращает false при обработке сообщения WM_NCCREATE, которое она получает во время CreateWindow. Я изменил его, чтобы он возвращал true, и теперь это удалось.

«CreateWindow завершается с ошибкой, если оконная процедура возвращает false» — большинство оконных сообщений возвращают 0 в случае успеха, если не указано иное. Создание окна завершается неудачно, если WM_NCCREATE возвращает 0 (ложь), вместо этого он должен возвращать 1 (истина). Но последующий WM_CREATE должен возвращать 0. Правильный подход состоит в том, чтобы ваша оконная процедура вызывала DefWindowProc() для любого сообщения, которое она не обрабатывает явно, и возвращала все, что возвращает `DefWindowProc().

Remy Lebeau 18.03.2024 02:57

Это хорошее разъяснение

mobslicer152 18.03.2024 03:20

Другие вопросы по теме