GUI - приложение с кнопкой

Тема в разделе "WASM.BEGINNERS", создана пользователем Entropy, 11 янв 2026.

Статус темы:
Закрыта.
  1. Entropy

    Entropy Member

    Публикаций:
    0
    Регистрация:
    23 авг 2020
    Сообщения:
    255
    Пытаюсь сделать графическое 32bit приложение с кнопкой,создаётся только окно,и после этого приложение зависает,ОС:Windows 10

    Код (ASM):
    1.  
    2. .686p
    3. option casemap:none
    4. .model flat,stdcall
    5.  
    6.  
    7.  
    8.  
    9.  
    10. main          PROTO :DWORD,:DWORD,:DWORD,:DWORD
    11. wndproc          PROTO :DWORD,:DWORD,:DWORD,:DWORD
    12.  
    13. include  include\windows.inc
    14. include  include\kernel32.inc
    15. include  include\msvcrt.inc
    16. include  include\user32.inc
    17.  
    18. includelib lib\kernel32.lib
    19. includelib lib\msvcrt.lib
    20. includelib lib\user32.lib
    21.  
    22. .data
    23.  
    24.  
    25. name_win_class db 'wclass',0
    26. caption db 'win10',0
    27.  
    28. button db 'button',0
    29.  
    30. .code
    31.  
    32. main proc inst:dword,previnst:dword,pcmdline:dword,cmdshow:dword
    33.  
    34. local win_msg:MSG
    35. local wc:WNDCLASSEX
    36. local win_desc:dword
    37. local btn_desc:dword
    38.    
    39.     mov wc.cbSize,sizeof WNDCLASSEX
    40.     mov wc.style,0
    41.     mov wc.lpfnWndProc,offset wndproc
    42.     mov wc.cbClsExtra,0
    43.     mov wc.cbWndExtra,0
    44.  
    45.     mov eax,dword ptr [inst]
    46.  
    47.     mov wc.hInstance,eax    
    48.     mov wc.hbrBackground,COLOR_BTNFACE+1
    49.     mov wc.lpszMenuName,0
    50.     mov wc.lpszClassName,offset name_win_class
    51.     mov wc.hIcon,0
    52.     mov wc.hCursor,0
    53.     mov wc.hIconSm,0
    54.  
    55. invoke RegisterClassEx,addr wc
    56. mov eax,dword ptr [inst]
    57.  
    58.  
    59. invoke CreateWindowEx,0,addr name_win_class,addr caption,WS_VISIBLE or WS_CAPTION or WS_SYSMENU or WS_OVERLAPPED,100,100,400,400,0,0,eax,0
    60.  
    61. mov win_desc,eax
    62.  
    63. mov ebx,dword ptr [inst]
    64. invoke CreateWindowEx,0,addr button,addr caption,WS_CHILD or WS_VISIBLE or WS_BORDER or BS_PUSHBUTTON,100,100,30,30,eax,0,ebx,0
    65.  
    66.  
    67.  
    68. msgloop:
    69. invoke GetMessage,addr win_msg,eax,0,0
    70.  
    71. invoke TranslateMessage,addr win_msg
    72. invoke DispatchMessage,addr win_msg
    73. mov eax,dword ptr [win_desc]
    74. jmp msgloop
    75.  
    76.          
    77. main endp
    78.  
    79.  
    80.  
    81. wndproc proc hWin   :DWORD,
    82.              uMsg   :DWORD,
    83.              wParam :DWORD,
    84.              lParam :DWORD
    85.  
    86.     cmp DWORD PTR uMsg, WM_DESTROY
    87.     jne @F
    88.       invoke ExitProcess,0
    89.      
    90.     @@:
    91.  
    92.     invoke DefWindowProc,hWin,uMsg,wParam,lParam
    93.  
    94.     ret
    95.  
    96. wndproc endp
    97.  
    98. end
    99.  
     
  2. f13nd

    f13nd Well-Known Member

    Публикаций:
    0
    Регистрация:
    22 июн 2009
    Сообщения:
    2.106
    Во-первых что за прототип main() такой и с какой стати hInstance ей передается? Если это точка входа из pe-заголовка, то оно int main(void). hInstance надо как-нибудь самому, GetModuleHandleA'ом например. Батон надо в WM_CREATE создавать и не отдавать это событие DefWindowProc'у. Тогда и батон нарисуется и курсор висячим не будет (это и есть зависание?) То, что у тебя было, по идее кое-как но работает на вин11. Если таки виснет, надо в отладчике выяснять почему.
    изображение_2026-01-11_130710959.png
    Код (Text):
    1. format pe gui 4.0 at hInstance
    2. hInstance = 0x400000
    3. include 'win32ax.inc'
    4. entry main
    5.  
    6. section '.code' code data readable executable
    7.  
    8. name_win_class db 'wclass',0
    9. caption db 'win10',0
    10. button db 'button',0
    11.  
    12. proc  main ;inst,previns,pcmdline,cmdshow
    13.     locals
    14.         win_msg MSG
    15.         wc WNDCLASSEX
    16.         win_desc dd ?
    17.         btn_desc dd ?
    18.     endl
    19.     mov [wc.cbSize],sizeof.WNDCLASSEX
    20.     mov [wc.style],0
    21.     mov [wc.lpfnWndProc],wndproc
    22.     mov [wc.cbClsExtra],0
    23.     mov [wc.cbWndExtra],0
    24.     ;mov eax,dword [inst]
    25.     ;
    26.     ;mov [wc.hInstance],eax
    27.     mov [wc.hInstance],hInstance
    28.    
    29.     mov [wc.hbrBackground],COLOR_BTNFACE+1
    30.     mov [wc.lpszMenuName],0
    31.     mov [wc.lpszClassName],name_win_class
    32.     mov [wc.hIcon],0
    33.     mov [wc.hCursor],0
    34.     mov [wc.hIconSm],0
    35. invoke RegisterClassEx,addr wc
    36. ;mov eax,dword[inst]
    37. ;invoke CreateWindowEx,0,addr name_win_class,addr caption,WS_VISIBLE or WS_CAPTION or WS_SYSMENU or WS_OVERLAPPED,100,100,400,400,0,0,eax,0
    38. invoke CreateWindowEx,0,addr name_win_class,addr caption,WS_VISIBLE or WS_CAPTION or WS_SYSMENU or WS_OVERLAPPED,100,100,400,400,0,0,hInstance,0
    39. mov [win_desc],eax
    40. ;mov ebx,dword [inst]
    41. ;invoke CreateWindowEx,0,addr button,addr caption,WS_CHILD or WS_VISIBLE or WS_BORDER or BS_PUSHBUTTON,100,100,30,30,eax,0,ebx,0
    42. ;invoke CreateWindowEx,0,addr button,addr caption,WS_CHILD or WS_VISIBLE or WS_BORDER or BS_PUSHBUTTON,100,100,30,30,eax,0,hInstance,0
    43. msgloop:
    44. invoke GetMessage,addr win_msg,eax,0,0
    45. invoke TranslateMessage,addr win_msg
    46. invoke DispatchMessage,addr win_msg
    47. mov eax,dword [win_desc]
    48. jmp msgloop
    49.      
    50. endp
    51. proc wndproc hWin,uMsg,wParam,lParam
    52.     ;cmp [uMsg], WM_DESTROY
    53.     ;jne @F
    54.     ;  invoke ExitProcess,0
    55.     ;
    56.     ;@@:
    57.     .if [uMsg] = WM_CREATE
    58.         invoke CreateWindowEx,0,addr button,addr caption,WS_CHILD or WS_VISIBLE or WS_BORDER or BS_PUSHBUTTON,100,100,30,30,[hWin],0,hInstance,0
    59.     .elseif [uMsg] = WM_DESTROY
    60.         invoke PostQuitMessage,0
    61.     .else
    62.         invoke DefWindowProc,[hWin],[uMsg],[wParam],[lParam]
    63.      .endif
    64.     ret
    65. endp
    66.  
    67. section '.data' data readable writable
    68. data import
    69.     library kernel32,'kernel32.dll',user32,'user32.dll'
    70.     include 'api\kernel32.inc'
    71.     include 'api\user32.inc'
    72. end data
     
  3. Ahimov

    Ahimov Active Member

    Публикаций:
    0
    Регистрация:
    14 окт 2024
    Сообщения:
    483
    - Gemini.

    Крутится и висит для бота без разницы :)
    --- Сообщение объединено, 11 янв 2026 ---
    Молодец!
     
    Последнее редактирование: 11 янв 2026
  4. Mikl___

    Mikl___ Супермодератор Команда форума

    Публикаций:
    14
    Регистрация:
    25 июн 2008
    Сообщения:
    4.205
    Entropy,
    а почему 32-разрядное приложение в Win10? А не как положено 64?
    Код (ASM):
    1. ; GUI #
    2. include win64a.inc
    3. SAVE macro REG
    4.    for R,<REG>
    5.       push R
    6.    endm
    7. endm
    8. .code
    9. WinMain proc
    10. local msg:MSG
    11.  
    12.        xor ebx,ebx
    13.        invoke LoadCursorFromFileA,"br_Rabbit3.cur"
    14.        mov esi,offset WndProc
    15.        mov edi,offset ClassName
    16. SAVE <rax,rdi,rbx,COLOR_WINDOW,rax,rax,IMAGE_BASE,rbx,rsi,(sizeof WNDCLASSEX)>
    17.        invoke RegisterClassExA,esp
    18. SAVE <rbx,IMAGE_BASE,rbx,rbx,400,400,CW_USEDEFAULT,CW_USEDEFAULT>
    19.        sub esp,20h
    20.        invoke CreateWindowExA,0,edi,edi,WS_OVERLAPPEDWINDOW or WS_VISIBLE
    21.        lea edi,msg
    22. @@:    invoke GetMessageA,edi,0,0,0
    23.        invoke DispatchMessageA,edi
    24.        jmp @b
    25. WinMain endp
    26. ;----------------------------------------
    27. WndProc proc hWnd:HWND,uMsg:UINT,wParam:WPARAM,lParam:LPARAM
    28.         mov hWnd,rcx
    29. for uMsg,<DESTROY,CREATE>
    30.         cmp edx,WM_&uMsg
    31.         je wm&uMsg
    32. endm
    33.         leave
    34.         jmp NtdllDefWindowProc_
    35. wmDESTROY:invoke RtlExitUserProcess,0
    36. wmCREATE:SAVE <0,IMAGE_BASE,0,rcx,30,130,30,30>
    37.         sub esp,20h
    38.         invoke CreateWindowExA,0,"button","Нажми на меня",WS_CHILD or WS_VISIBLE or WS_BORDER or BS_PUSHBUTTON
    39.         leave
    40.         retn
    41. WndProc endp
    42. .data;-----------------------------------------
    43. ClassName db 'Entropy',0
    44. end
    00.png
    Во вложении asm-/exe-/cur-файлы
     

    Вложения:

    • Entropy.zip
      Размер файла:
      3 КБ
      Просмотров:
      97
  5. Ahimov

    Ahimov Active Member

    Публикаций:
    0
    Регистрация:
    14 окт 2024
    Сообщения:
    483
    Mikl___

    Архитектура сложнее, вначале идет 86.
     
  6. Mikl___

    Mikl___ Супермодератор Команда форума

    Публикаций:
    14
    Регистрация:
    25 июн 2008
    Сообщения:
    4.205
    Ahimov,
    чтобы собрать окошко с кнопкой в x64 знаний об архитектуре x86 будет вполне достаточно, но +8 новых РОН, а передача параметров через регистры и стек скрывается при использовании invoke
    GRAFik,
    вот прекрасный пример флуда. Вас просят помочь с конкретной программой, а Вы начинаете разговор о ИИ, визоре и музыке :negative: Пока, предупреждение...
     
    Ahimov нравится это.
  7. Ahimov

    Ahimov Active Member

    Публикаций:
    0
    Регистрация:
    14 окт 2024
    Сообщения:
    483
    Mikl___

    Но когда он откроет отладчиком, увидит длинные адреса, не понятную сегментацию и межпроцедурный обмен контекстом.
     
  8. Mikl___

    Mikl___ Супермодератор Команда форума

    Публикаций:
    14
    Регистрация:
    25 июн 2008
    Сообщения:
    4.205
    Ahimov,
    в этом и прелесть masm ― можно настроить все под себя. А использование отладчика ― это обязательный атрибут написания программ на ассемблере :yes3:
     
  9. Entropy

    Entropy Member

    Публикаций:
    0
    Регистрация:
    23 авг 2020
    Сообщения:
    255
    f13nd, это моё первое графическое приложение,а раньше я писал консольные приложения и закладывал в них алгоритм распознавания введённых строк,кстати проблема была в функции GetMessage,получилось так что не тот дескриптор передал
    Код (ASM):
    1.  
    2. 686p
    3. option casemap:none
    4. .model flat,stdcall
    5.  
    6.  
    7.  
    8.  
    9.  
    10. main          PROTO :DWORD,:DWORD,:DWORD,:DWORD
    11. wndproc          PROTO :DWORD,:DWORD,:DWORD,:DWORD
    12.  
    13. include windows.inc
    14. include kernel32.inc
    15. include msvcrt.inc
    16. include user32.inc
    17.  
    18. includelib papak\wlib\kernel32.lib
    19. includelib papak\wlib\msvcrt.lib
    20. includelib papak\wlib\user32.lib
    21.  
    22. .data
    23.  
    24.  
    25. name_win_class db 'wclass',0
    26. caption db 'win10',0
    27.  
    28. button db 'button',0
    29.  
    30. .code
    31.  
    32. main proc inst:dword,previnst:dword,pcmdline:dword,cmdshow:dword
    33.  
    34. local win_msg:MSG
    35. local wc:WNDCLASSEX
    36. local win_desc:dword
    37. local btn_desc:dword
    38.    
    39. invoke     GetModuleHandleA,0
    40.  
    41.     mov wc.cbSize,sizeof WNDCLASSEX
    42.     mov wc.style,0
    43.     mov wc.lpfnWndProc,offset wndproc
    44.     mov wc.cbClsExtra,0
    45.     mov wc.cbWndExtra,0
    46.     mov wc.hInstance,eax    
    47.     mov wc.hbrBackground,COLOR_BTNFACE+1
    48.     mov wc.lpszMenuName,0
    49.     mov wc.lpszClassName,offset name_win_class
    50.     mov wc.hIcon,0
    51.     mov wc.hCursor,0
    52.     mov wc.hIconSm,0
    53.  
    54. invoke RegisterClassEx,addr wc
    55. mov eax,dword ptr [wc.hInstance]
    56.  
    57.  
    58. invoke CreateWindowEx,0,addr name_win_class,addr caption,WS_VISIBLE or WS_CAPTION or WS_SYSMENU or WS_OVERLAPPED,100,100,400,400,0,0,eax,0
    59.  
    60. mov win_desc,eax
    61.  
    62. mov ebx,dword ptr [wc.hInstance]
    63. invoke CreateWindowEx,0,addr button,addr caption,WS_CHILD or WS_VISIBLE or WS_BORDER or BS_PUSHBUTTON,100,100,30,30,eax,0,ebx,0
    64.  
    65.  
    66. mov eax,dword ptr [win_desc]
    67. msgloop:
    68. invoke GetMessage,addr win_msg,eax,0,0
    69.  
    70. invoke TranslateMessage,addr win_msg
    71. invoke DispatchMessage,addr win_msg
    72. mov eax,dword ptr [win_desc]
    73. jmp msgloop
    74.  
    75.          
    76. main endp
    77.  
    78.  
    79.  
    80. wndproc proc hWin   :DWORD,
    81.              uMsg   :DWORD,
    82.              wParam :DWORD,
    83.              lParam :DWORD
    84.  
    85.     cmp DWORD PTR uMsg, WM_DESTROY
    86.     jne @F
    87.       invoke ExitProcess,0
    88.      
    89.     @@:
    90.  
    91.     invoke DefWindowProc,hWin,uMsg,wParam,lParam
    92.  
    93.     ret
    94.  
    95. wndproc endp
    96.  
    97. end
    98.  
    --- Сообщение объединено, 12 янв 2026 ---
    я это приму к сведению
     
  10. Mikl___

    Mikl___ Супермодератор Команда форума

    Публикаций:
    14
    Регистрация:
    25 июн 2008
    Сообщения:
    4.205
    Entropy,
    я бы порекомендовал вам книжки, которые есть в ресурсах:
    • Чарльз Петзолд "Программирование для Windows"
    • Герберт Шилдт "Программирование на С и С++ для Windows"
    • Сергей Норсеев "РАЗРАБОТКА ОКОННЫХ ПРИЛОЖЕНИЙ НА FASMе"
    узнаете много нового, жалко, что на мой вариант вы решили не обращать внимание... :scratch_one-s_head:
     
    Последнее редактирование: 12 янв 2026
    Application нравится это.
  11. Mikl___

    Mikl___ Супермодератор Команда форума

    Публикаций:
    14
    Регистрация:
    25 июн 2008
    Сообщения:
    4.205
    00.png
    «Если бы губы Никанора Ивановича да приставить к носу Ивана Кузьмича, да взять сколько-нибудь развязности, какая у Балтазара Балтазарыча, да, пожалуй, прибавить к этому еще дородности Ивана Павловича...»
    (© Н.В.Гоголь «Женитьба»)​
     

    Вложения:

    • Entropy.zip
      Размер файла:
      6,6 КБ
      Просмотров:
      95
    Application нравится это.
  12. Entropy

    Entropy Member

    Публикаций:
    0
    Регистрация:
    23 авг 2020
    Сообщения:
    255
    32 битный ассемблер чуть легче,но всё же он есть ассемблер
    --- Сообщение объединено, 17 янв 2026 ---
    Mikl___, кстати открыл ваш пример отладчиком,вы разместили структуру WNDCLASSEXA полностью в стёке и функция RegisterClassEx как-то эту структуру смогла прочесть
     

    Вложения:

  13. Mikl___

    Mikl___ Супермодератор Команда форума

    Публикаций:
    14
    Регистрация:
    25 июн 2008
    Сообщения:
    4.205
    А чему удивляться? Данные в виде структуры WNDCLASSEXA в стеке, а в единственном параметре RegisterClassEx указатель на верхушку стека. Структуру WNDCLASSEXA (как и другие переменные) можно размещать:
    • в секциях .data, .data?, .const
    • в секции .code, если требуется только чтение
    • в локальных переменных процедуры WinMain (как в примере f13nd),
    • а также затолкать (to push) в стек.
    Ограничений на размещение WNDCLASSEXA я нигде не видел ;) ...
     
  14. Entropy

    Entropy Member

    Публикаций:
    0
    Регистрация:
    23 авг 2020
    Сообщения:
    255
    Mikl___, получается что функция RegisterClassEx прибавляет к полученному указателю смещение,для последовательного чтения всех полей структуры
     
  15. Ahimov

    Ahimov Active Member

    Публикаций:
    0
    Регистрация:
    14 окт 2024
    Сообщения:
    483
    Entropy

    Аргументы rCx - rDx - r8 - r9: x64-calling-convention

    Структура формируется в стеке, в ecx загружается указатель на начало структуры esp. Почему не rcx -> rsp - старшая часть рандом, стек в нижней части набора и так совпало что после 40100D старшая часть rcx обнулена, иначе закрэшит, rCx = f(40100D()) | eSp
     
  16. Mikl___

    Mikl___ Супермодератор Команда форума

    Публикаций:
    14
    Регистрация:
    25 июн 2008
    Сообщения:
    4.205
    Entropy,
    да, именно так, и еще почитай здесь Программные соглашения x64 | WASM
    Ahimov,
    при линковке использовались ключи /LARGEADDRESSAWARE:NO и /BASE:0x400000 32-разрядные регистры (esp, ecx и т.д) использовались для формирования программы с более компактным кодом (это у меня бзик такой был). Подробнее здесь Сказки дядюшки Римуса о x64, там в первых двух статьях всё подробно расписано
     
  17. Ahimov

    Ahimov Active Member

    Публикаций:
    0
    Регистрация:
    14 окт 2024
    Сообщения:
    483
    Mikl___

    LoadCursor() -> rCx: rand -> RegisterClass(rCx)

    - старшая часть не определена.
     
  18. Mikl___

    Mikl___ Супермодератор Команда форума

    Публикаций:
    14
    Регистрация:
    25 июн 2008
    Сообщения:
    4.205
    Ahimov,
    старшая часть 64-разрядного адреса при /LARGEADDRESSAWARE:NO обнуляется
    lea rcx,FileName -> LoadCursorFromFile() -> rax и передается в wc.hIcon, wc.hCursor и wc.hIconSm
    при переключении из 64-разрядного режима в режим совместимости или обратно содержимое старших 32 битов регистров RAX, RBX, RCX, RDX, RSI, RDI, RBP и RSP не сохраняется. Содержимое регистров R8–R15 в аналогичной ситуации сохраняется
    Запись в младшие 32-бита регистров RAX, RBX, RCX, RDX, RSI, RDI, RBP и RSP обнуляют старшую часть 64-битного регистра
     
  19. Entropy

    Entropy Member

    Публикаций:
    0
    Регистрация:
    23 авг 2020
    Сообщения:
    255
    Mikl___, я понимаю что в х64 прежде чем вызвать функцию, из регистра RSP нужно вычесть 8 * (количество аргументов + 1),это если функция больше принимает больше 4 аргументов,если меньше 4 тогда просто SUB RSP,40 так что смысла мне это читать как-бы нет,ну если речь пойдет об обработке исключений в х64 тогда нужно будет почитать
     
  20. Dmitry_Milk

    Dmitry_Milk Member

    Публикаций:
    0
    Регистрация:
    20 ноя 2007
    Сообщения:
    568
    В конвенции x64 проще вообще не играться стеком перед каждым вызовом, а сразу в прологе стекфрейма текущей функции зарезервировать место под наибольшее количество (или минимум 4) параметров любых вызовов внутри текущей функции, и в большинстве случаев просто сразу фигачить CALL без каких-либо игрищ со стеком, а лишь положив параметры в регистры. А сохранением содержимого этих регистров в зарерервированнх слотах стека пусть занимается вызываемая функция (если ей вообще это надо, т.к. конвенция этого не требует, конвенция требует только от вызывающей функции зарезервировать эти слоты).
     
    Mikl___ нравится это.
Статус темы:
Закрыта.