flat assembler
Message board for the users of flat assembler.

Index > Windows > [solved] x64 Simple Window never appears

Author
Thread Post new topic Reply to topic
avidichard



Joined: 22 Mar 2021
Posts: 10
Location: Quebec/Canada
avidichard
Code:
format PE64 GUI 6.0
entry sec_start

include 'win64w.inc'

section '.idata' import data readable writeable
  library kernel32,'KERNEL32.DLL',\
          user32,  'USER32.DLL'
        
  import kernel32,\
         GetModuleHandle, 'GetModuleHandleA',\
         ExitProcess, 'ExitProcess'
  import user32,\
         RegisterClassEx, 'RegisterClassExA',\
         CreateWindowEx, 'CreateWindowExA',\
         DefWindowProc, 'DefWindowProcA',\
         GetMessage, 'GetMessageA',\
                                 TranslateMessage, 'TranslateMessage',\
         DispatchMessage, 'DispatchMessageA',\
                                 ShowWindow, 'ShowWindow',\
                                 PostQuitMessage, 'PostQuitMessage',\
                                 LoadIcon, 'LoadIconA',\
                                 LoadCursor, 'LoadCursorA'

section '.data' data readable writeable
  s_ClassTitle TCHAR "My program's window title", 0 ; Set window title and class name
        
        wc WNDCLASSEX ?
        msg MSG ?
        
        l_hWnd dq ?
        l_hInstance dq ?

section '.text' code readable writeable executable

        sec_start:
                invoke GetModuleHandle, NULL
                mov [l_hInstance], rax
                mov [wc.hInstance], rax
                
                mov [wc.cbSize], sizeof.WNDCLASSEX
                mov [wc.style], CS_HREDRAW or CS_VREDRAW
                mov [wc.lpfnWndProc], procWnd
                mov [wc.cbClsExtra], 0
                
                invoke LoadIcon, 0, IDI_APPLICATION
                mov [wc.hIcon], rax
                mov [wc.hIconSm], rax
                
                invoke LoadCursor, 0, IDC_ARROW
                mov [wc.hCursor], rax
                
                mov [wc.hbrBackground], COLOR_WINDOW+1
                mov [wc.lpszMenuName], NULL
                mov [wc.lpszClassName], s_ClassTitle
                
                invoke RegisterClassEx, wc
                invoke CreateWindowEx, 0, s_ClassTitle, s_ClassTitle, WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, 640, 480, NULL, NULL, [l_hInstance], NULL
                mov [l_hWnd], rax
                invoke ShowWindow, [l_hWnd], SW_SHOW

        sec_msg_loop:
                invoke GetMessage, msg, NULL, 0, 0
                or rax, rax
                je sec_end_prog
                
                invoke TranslateMessage, msg
                invoke DispatchMessage, msg
                jmp sec_msg_loop
        
        sec_end_prog:
                invoke ExitProcess, [msg.wParam]
        
        proc procWnd hWnd, msg, wParam, lParam
                push rbx rsi rdi
                cmp [msg], WM_DESTROY
                je sec_destroy_wnd
                
                invoke DefWindowProc, [hWnd], [msg], [wParam], [lParam]
                jmp sec_finish
                
                sec_destroy_wnd:
                        invoke PostQuitMessage,0
                        
                sec_finish:
                        pop rbx rsi rdi
                        ret
endp    


I am just starting use FASM. I chose to go with a very basic Window in x64 NOT x86. So I came up with this code following a similar code from another FASM post I found. When I run it in FASMW, the window never appears, NO error messages show up and no process is present in Windows task manager.

The 32 bits version of this code works, I just wanted to make it a 64 bits. I seams to have failed or missed a detail.

I supplied the ASM file in the attachments.


Description:
Download
Filename: prjTest.asm
Filesize: 2.21 KB
Downloaded: 15 Time(s)

Post 20 Jul 2021, 00:00
View user's profile Send private message Reply with quote
bitRAKE



Joined: 21 Jul 2003
Posts: 3230
Location: vpcmipstrm
bitRAKE
The include file 'win64w.inc' does not align the stack. So, when RegisterClassEx uses XMM register instructions (which require 16 byte alignment) an exception is generated. Once this error is resolved the same alignment error takes place within procWnd.

The PROC/ENDP macros support a USES keyword to preserve registers - if you use it then it will align the stack correctly. Example,
Code:
proc procWnd uses rbx rsi rsi, hWnd, msg, wParam, lParam
        cmp [msg], WM_DESTROY
        je sec_destroy_wnd
        
        invoke DefWindowProc, [hWnd], [msg], [wParam], [lParam]
        jmp sec_finish
        
        sec_destroy_wnd:
                invoke PostQuitMessage,0
                
        sec_finish:
                ret
endp    
As for the initial alignment it is sufficient to PUSH RAX at program start.

Additionally, there is the problem of using APIs which expect byte strings, but then including WCHAR support and TCHAR strings.

And finally, PROC/ENDP does not store fastcall register parameters in the shadow space.

Working program with needed changes becomes:
Code:
format PE64 GUI 6.0
entry sec_start

include 'win64a.inc'

section '.idata' import data readable writeable
  library kernel32,'KERNEL32.DLL',\
          user32,  'USER32.DLL'
        
  import kernel32,\
         GetModuleHandle, 'GetModuleHandleA',\
         ExitProcess, 'ExitProcess'
  import user32,\
         RegisterClassEx, 'RegisterClassExA',\
         CreateWindowEx, 'CreateWindowExA',\
         DefWindowProc, 'DefWindowProcA',\
         GetMessage, 'GetMessageA',\
                                 TranslateMessage, 'TranslateMessage',\
         DispatchMessage, 'DispatchMessageA',\
                                 ShowWindow, 'ShowWindow',\
                                 PostQuitMessage, 'PostQuitMessage',\
                                 LoadIcon, 'LoadIconA',\
                                 LoadCursor, 'LoadCursorA'

section '.data' data readable writeable

  s_ClassTitle TCHAR "My program's window title", 0 ; Set window title and class name
        
        wc WNDCLASSEX ?
        msg MSG ?
        
        l_hWnd dq ?
        l_hInstance dq ?

section '.text' code readable writeable executable

        sec_start:
                push rax
                invoke GetModuleHandle, NULL
                mov [l_hInstance], rax
                mov [wc.hInstance], rax
                
                mov [wc.cbSize], sizeof.WNDCLASSEX
                mov [wc.style], CS_HREDRAW or CS_VREDRAW
                mov [wc.lpfnWndProc], procWnd
                mov [wc.cbClsExtra], 0
                
                invoke LoadIcon, 0, IDI_APPLICATION
                mov [wc.hIcon], rax
                mov [wc.hIconSm], rax
                
                invoke LoadCursor, 0, IDC_ARROW
                mov [wc.hCursor], rax
                
                mov [wc.hbrBackground], COLOR_WINDOW+1
                mov [wc.lpszMenuName], NULL
                mov [wc.lpszClassName], s_ClassTitle
                
                invoke RegisterClassEx, wc
                invoke CreateWindowEx, 0, s_ClassTitle, s_ClassTitle, WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, 640, 480, NULL, NULL, [l_hInstance], NULL
                mov [l_hWnd], rax
                invoke ShowWindow, [l_hWnd], SW_SHOW

        sec_msg_loop:
                invoke GetMessage, msg, NULL, 0, 0
                or rax, rax
                je sec_end_prog
                
                invoke TranslateMessage, msg
                invoke DispatchMessage, msg
                jmp sec_msg_loop
        
        sec_end_prog:
                invoke ExitProcess, [msg.wParam]
                int3
        
        proc procWnd uses rbx rsi rsi, hWnd, msg, wParam, lParam
                mov [hWnd],rcx
                mov [msg],rdx
                mov [wParam],r8
                mov [lParam],r9

                cmp [msg], WM_DESTROY
                je sec_destroy_wnd
                
                invoke DefWindowProc, [hWnd], [msg], [wParam], [lParam]
                jmp sec_finish

                sec_destroy_wnd:
                        invoke PostQuitMessage,0
                        
                sec_finish:
                        ret
        endp    
I would like to suggest using a debugger.


Last edited by bitRAKE on 20 Jul 2021, 00:59; edited 1 time in total
Post 20 Jul 2021, 00:32
View user's profile Send private message Visit poster's website Reply with quote
avidichard



Joined: 22 Mar 2021
Posts: 10
Location: Quebec/Canada
avidichard
***EDIT***: I posted a few seconds after your post edit. Thanks, I'll give your code a fo Smile

Code:
format PE64 GUI 6.0
entry sec_start

include 'win64w.inc'

section '.idata' import data readable writeable
        library kernel32, 'KERNEL32.DLL',\
                user32, 'USER32.DLL'
        
  import kernel32,\
               GetModuleHandle, 'GetModuleHandleA',\
               ExitProcess, 'ExitProcess'
  import user32,\
               RegisterClassEx, 'RegisterClassExA',\
               CreateWindowEx, 'CreateWindowExA',\
               DefWindowProc, 'DefWindowProcA',\
               GetMessage, 'GetMessageA',\
               TranslateMessage, 'TranslateMessage',\
               DispatchMessage, 'DispatchMessageA',\
               ShowWindow, 'ShowWindow',\
               PostQuitMessage, 'PostQuitMessage',\
               LoadIcon, 'LoadIconA',\
               LoadCursor, 'LoadCursorA'

section '.data' data readable writeable
  s_ClassTitle TCHAR "My program's window title", 0 ; Set window title and class name
        
        wc WNDCLASSEX ?
        msg MSG ?
        
        l_hWnd dq ?
        l_hInstance dq ?

section '.text' code readable writeable executable

        sec_start:
                push rax
                invoke GetModuleHandle, NULL
                mov [l_hInstance], rax
                mov [wc.hInstance], rax
                
                mov [wc.cbSize], sizeof.WNDCLASSEX
                mov [wc.style], CS_HREDRAW or CS_VREDRAW
                mov [wc.lpfnWndProc], procWnd
                mov [wc.cbClsExtra], 0
                
                invoke LoadIcon, 0, IDI_APPLICATION
                mov [wc.hIcon], rax
                mov [wc.hIconSm], rax
                
                invoke LoadCursor, 0, IDC_ARROW
                mov [wc.hCursor], rax
                
                mov [wc.hbrBackground], COLOR_WINDOW+1
                mov [wc.lpszMenuName], NULL
                mov [wc.lpszClassName], s_ClassTitle
                
                invoke RegisterClassEx, wc
                invoke CreateWindowEx, 0, s_ClassTitle, s_ClassTitle, WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, 640, 480, NULL, NULL, [l_hInstance], NULL
                mov [l_hWnd], rax
                invoke ShowWindow, [l_hWnd], SW_SHOW

        sec_msg_loop:
                invoke GetMessage, msg, NULL, 0, 0
                or rax, rax
                je sec_end_prog
                
                invoke TranslateMessage, msg
                invoke DispatchMessage, msg
                jmp sec_msg_loop
        
        sec_end_prog:
                invoke ExitProcess, [msg.wParam]
        
        proc procWnd uses rbx rsi rsi, hWnd, msg, wParam, lParam
                cmp [msg], WM_DESTROY
                je sec_destroy_wnd
                
                invoke DefWindowProc, [hWnd], [msg], [wParam], [lParam]
                jmp sec_finish
                
                sec_destroy_wnd:
                        invoke PostQuitMessage,0
                        
                sec_finish:
                        ret
        endp    

Well, I get a difference. I connot compile anymore since there is a process running which I can see ONLY once FASMW is closed. Now I saw that you used "uses rbx rsi rsi" instead of "uses rbx rsi rdi".

But I end up with the same problem, no window appears. I also tried to pop rax after the ShowWindow but it did not help either. Process is there but window never appears.
Post 20 Jul 2021, 00:57
View user's profile Send private message Reply with quote
bitRAKE



Joined: 21 Jul 2003
Posts: 3230
Location: vpcmipstrm
bitRAKE
Sorry, I have edited my post extensively.

You'll need to terminate hung application in Task Manager to compile again.
Post 20 Jul 2021, 01:00
View user's profile Send private message Visit poster's website Reply with quote
avidichard



Joined: 22 Mar 2021
Posts: 10
Location: Quebec/Canada
avidichard
It's OK, I now have a window caption that only shows "M" and not the "My program's window title". I changed this line and it works great. I'll be able to finally move on to adding text boxes and other controls.
Code:
s_ClassTitle TCHAR "My program's window title", 0 ; Set window title and class name
; BECOMES
s_ClassTitle db "My program's window title", 0 ; Set window title and class name    

I am wondering if I should simply NOT include the win64w.inc file and simply call the constructs and vars myself. I know, I am not in the same programming style if I talk about VB6, but in VB6, we had to define all the variable and const such as MSG, WNDCLASSEX, CS_HREDRAW, etc... So defining those in FASM should not be too different asside from moving them in their proper addresses and space which is not needed in VB6.

I could maybe correct the disaligned problem by alligning those myself.

Basically, if I can remove the need to using win64w.inc or win64a.inc, that would be great. And as an example like this, all I need is the bare basics to create a window, nothing more and as I can see, the included files include a bunch of unused variables and structs.
Post 20 Jul 2021, 01:16
View user's profile Send private message Reply with quote
avidichard



Joined: 22 Mar 2021
Posts: 10
Location: Quebec/Canada
avidichard
bitRAKE wrote:
Sorry, I have edited my post extensively.

You'll need to terminate hung application in Task Manager to compile again.

It's Okay! I really cannot thank you enough for this. I've been scratching my head and googling for a few days. I'm dumping my old programming languages to program in FASM. It's longer and requires more work but I get to understand MUCH more and I feel less handicaped and more free to do what I want. And using Windows API calls is not new to me so all there is to do is to manually draw and position what's inside the windows instead of relying on predefined noob-proof GUIs.

I find ASM a mixture of HTML and VB6 where you have to manually code the position of your elements while relying on windows API calls to display a user interface. The only thing I have to learn is to mov those information using the proper mnemonics and registers. That's the part I need to understand which is still a bit fuzzy for me but I've read so much and went through the FASM guide and Wiki and much more.

Thank you very much for your very kind help!!!!
Post 20 Jul 2021, 01:23
View user's profile Send private message Reply with quote
avidichard



Joined: 22 Mar 2021
Posts: 10
Location: Quebec/Canada
avidichard
WORKING CODE: For those that may land here
Code:
format PE64 GUI 6.0
entry sec_start

include 'win64w.inc'

section '.idata' import data readable writeable
  library kernel32, 'KERNEL32.DLL',\
          user32, 'USER32.DLL'

import kernel32,\
  GetModuleHandle, 'GetModuleHandleA',\
        ExitProcess, 'ExitProcess'
import user32,\
  RegisterClassEx, 'RegisterClassExA',\
  CreateWindowEx, 'CreateWindowExA',\
  DefWindowProc, 'DefWindowProcA',\
  GetMessage, 'GetMessageA',\
  TranslateMessage, 'TranslateMessage',\
  DispatchMessage, 'DispatchMessageA',\
  ShowWindow, 'ShowWindow',\
  PostQuitMessage, 'PostQuitMessage',\
  LoadIcon, 'LoadIconA',\
  LoadCursor, 'LoadCursorA'

section '.data' data readable writeable
  s_ClassTitle db "My program's window title", 0 ; Set window title and class name
  wc WNDCLASSEX ?
  msg MSG ?
  l_hWnd dq ?
  l_hInstance dq ?

section '.text' code readable writeable executable

  sec_start:
    push rax
    invoke GetModuleHandle, NULL
    mov [l_hInstance], rax
    mov [wc.hInstance], rax

    mov [wc.cbSize], sizeof.WNDCLASSEX
    mov [wc.style], CS_HREDRAW or CS_VREDRAW
    mov [wc.lpfnWndProc], procWnd
    mov [wc.cbClsExtra], 0

    invoke LoadIcon, 0, IDI_APPLICATION
    mov [wc.hIcon], rax
    mov [wc.hIconSm], rax

    invoke LoadCursor, 0, IDC_ARROW
    mov [wc.hCursor], rax

    mov [wc.hbrBackground], COLOR_WINDOW+1
    mov [wc.lpszMenuName], NULL
    mov [wc.lpszClassName], s_ClassTitle

    invoke RegisterClassEx, wc
    invoke CreateWindowEx, 0, s_ClassTitle, s_ClassTitle, WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, 640, 480, NULL, NULL, [l_hInstance], NULL
    mov [l_hWnd], rax
    invoke ShowWindow, [l_hWnd], SW_SHOW

  sec_msg_loop:
    invoke GetMessage, msg, NULL, 0, 0
    or rax, rax
    je sec_end_prog

    invoke TranslateMessage, msg
    invoke DispatchMessage, msg
    jmp sec_msg_loop

  sec_end_prog:
    invoke ExitProcess, [msg.wParam]

  proc procWnd uses rbx rsi rsi, hWnd, msg, wParam, lParam
    mov [hWnd], rcx
    mov [msg], rdx
    mov [wParam], r8
    mov [lParam], r9
    cmp [msg], WM_DESTROY
    je sec_destroy_wnd

    invoke DefWindowProc, [hWnd], [msg], [wParam], [lParam]
    jmp sec_finish

    sec_destroy_wnd:
      invoke PostQuitMessage,0

    sec_finish:
      ret
  endp    
Post 20 Jul 2021, 01:28
View user's profile Send private message Reply with quote
bitRAKE



Joined: 21 Jul 2003
Posts: 3230
Location: vpcmipstrm
bitRAKE
avidichard wrote:
I am wondering if I should simply NOT include the win64w.inc file and simply call the constructs and vars myself.
One of the benefits of FASM beyond other assemblers is that it's macro capabilities scale quite robustly - meaning that you can build a system that works for you at higher levels of complexity. The system of macros included with FASM are one example of this. As you sense the lower-level understanding that is there, so too is there a higher-level understanding that you can create. fasmg takes the above concept even further by defining the assembler itself in the macro language.

The debugger is a great way to learn assembler. Instructions can be assembled within and executed at will - while watching the machine state change. "What did that do to the flags or stack?"

Whichever way forward you decide will depend on your goals. Having so much control can induce paralysis if you are not careful. Assembly is a lot of control - every bit is at your whim. Every level of abstraction looks out across a sea of change and down an infinite chasm of choice. To set sail or rappel?

_________________
¯\(°_o)/¯ unlicense.org
Post 20 Jul 2021, 02:07
View user's profile Send private message Visit poster's website Reply with quote
avidichard



Joined: 22 Mar 2021
Posts: 10
Location: Quebec/Canada
avidichard
I just realised that the IF, STRUCT and other easy stuff is just part of macros and not actually part of the Assembly language. I thought macros were part of assembly but as I can see, they are NOT. I understand now why we "include" those files now. I thought I could simply ask for a conditional IF with the IF statement but NOOOOO, the macros actually CREATE the if command.

I got your point on paralysis now. Well, I'm actually happy that I have changed my code a bit. Just realised that the LoadCursor and LoadIcon were not necessary to actually run my window.

I also chose to start building my own webpage to learn assembly. It's just local for personal use for now until I get AT LEAST something that looks like knowledge. but I'me using this as my color coded code editor

I'm used to put images in spoilers but this is how my tool looks like and I love the colors I chose. It also properly indents the code.

Well, I guess I can consider this thread closed because I got my solution. Again, a very huge and big thank you for the help. This REALLY got me going!!!

A few screenshots of my personal local website about FASM.

Image

Image

Image
Post 20 Jul 2021, 07:03
View user's profile Send private message Reply with quote
revolution
When all else fails, read the source


Joined: 24 Aug 2004
Posts: 18109
Location: In your JS exploiting you and your system
revolution
avidichard wrote:
I thought I could simply ask for a conditional IF with the IF statement but NOOOOO, the macros actually CREATE the if command.
There is an important distinction though.

if without any dot, is a native part of the assembler. You can override this behaviour with a macro, but the default macros that come with fasm don't.

.if with a leading dot, is a macro.
Post 20 Jul 2021, 07:17
View user's profile Send private message Visit poster's website Reply with quote
avidichard



Joined: 22 Mar 2021
Posts: 10
Location: Quebec/Canada
avidichard
revolution wrote:
avidichard wrote:
I thought I could simply ask for a conditional IF with the IF statement but NOOOOO, the macros actually CREATE the if command.
There is an important distinction though.

if without any dot, is a native part of the assembler. You can override this behaviour with a macro, but the default macros that come with fasm don't.

.if with a leading dot, is a macro.


Thanks a lot for the precision. I am really enjoying this community. Thank a lot! Very Happy
Post 20 Jul 2021, 07:20
View user's profile Send private message Reply with quote
revolution
When all else fails, read the source


Joined: 24 Aug 2004
Posts: 18109
Location: In your JS exploiting you and your system
revolution
It is the same for struc vs struct. The first is native, the second is a macro.

Also note the letter case. The native version allows mixed case. The default macros only define the lower case version.
Post 20 Jul 2021, 07:28
View user's profile Send private message Visit poster's website Reply with quote
avidichard



Joined: 22 Mar 2021
Posts: 10
Location: Quebec/Canada
avidichard
VERY basic (work in progress) FASM windows tutorial

I just uploaded what I have so far of my FASM tutorial. Of course, this was meant to be for personal use only and to be worked on but at least, it's there somewhere for someone and I can most definately get feedback from others. But I finaly have a working x64 FASM code for a basic window so I now consider my project worth working on now. I also love the modern style of my web page and I want to add more to it.

I honestly cannot thank you enough for all your precious comments, solutions and suggestions such as the debugger app that I love.
Post 21 Jul 2021, 00:01
View user's profile Send private message Reply with quote
Display posts from previous:
Post new topic Reply to topic

Jump to:  


< Last Thread | Next Thread >
Forum Rules:
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum
You cannot attach files in this forum
You can download files in this forum


Copyright © 1999-2020, Tomasz Grysztar. Also on GitHub, YouTube, Twitter.

Website powered by rwasa.