flat assembler
Message board for the users of flat assembler.

Index > Windows > Why is creating a window so incredibly frustrating.

Author
Thread Post new topic Reply to topic
Byte_Blast



Joined: 01 Jul 2026
Posts: 5
Location: Australia
Byte_Blast 02 Jul 2026, 12:55
First off, i just want to say that i am still relatively new to assembly programming, and this is my first post on the entire forum, so if you see any mistakes in anything i say or see in my code, please attribute it to my in-experience.

Alright, so i've been trying to do a very simple program that just displays a window with a few custom parameters, which namely follows closely to the TEMPLATE.ASM file located in C:\Program Files\FASM\EXAMPLES\TEMPLATE

I've been reading the following book Programming Windows 5th Edition(Charles Petzold), although a very old book, much of the information in there is still relative to the Win API because of microsofts backwards compatibility approach.

As well as scouring the Win API index for various functions that are needed to run this simple program, along with other things that required reading on my part.

From what i understand, a program that simply displays a window follows the following steps.

INITIALIZATION:
GetModuleHandle
LoadIcon
LoadCursor
LoadBrush (optional)
RegisterClass (pointer to WNDCLASS structure)
CreateWindowEx

MESSAGE_LOOP:
GetMessage
TranslateMessage
DispatchMessage

WindowProc (custom parameters)

I could optionally include the functions ShowWindow & UpdateWindow, but seeing as the TEMPLATE.ASM doesn't use them i am assuming that will be handled by DefWindowProc inside WindowProc.

Now here's my issue, i have been trying for probably 2 days now trying to get my program to display a window. I have read every single piece of documentation on each of the functions used, but the program always fails at CreateWindowEx function, which i confirmed using WinDbg.

The thing that perplexes me even more, is that i can make my program practically identical to TEMPLATE.ASM and it will still fail even when WNDCLASS has the same loaded parameters as TEMPLATE.ASM and the parameters for CreateWindowEx is the same as TEMPLATE.ASM

It is only if (and only if) i replace the entire WindProc from my program with the one from TEMPLATE.ASM that the program will actually run, which again, is very,very weird because my code is relatively the same to TEMPLATE.ASM.

So therefore, i am at a loss, maybe someone here will point out the obvious to me, and for clarification, i didn't bother to include any error control in my program because i can find the problem in WinDbg myself.


Description:
Download
Filename: windowtest.asm
Filesize: 1.23 KB
Downloaded: 23 Time(s)

Post 02 Jul 2026, 12:55
View user's profile Send private message Reply with quote
macomics



Joined: 26 Jan 2021
Posts: 1220
Location: Russia
macomics 02 Jul 2026, 14:45
Since you are using macros to create WindowProc, you must also return from the function using the ret macro (in small letters). RET generates a simple assembler command, not a macro instruction to exit WindowProc.
Post 02 Jul 2026, 14:45
View user's profile Send private message Reply with quote
MаtQuasar



Joined: 22 Jun 2026
Posts: 11
MаtQuasar 02 Jul 2026, 14:48
You did not move return value of CreateWindowEx to hwnd.

Code:
mov     [hwnd],eax    


EDIT: Okay, not necessary, because TEMPLATE.ASM does not have it.
Post 02 Jul 2026, 14:48
View user's profile Send private message Reply with quote
Byte_Blast



Joined: 01 Jul 2026
Posts: 5
Location: Australia
Byte_Blast 02 Jul 2026, 15:09
macomics wrote:
Since you are using macros to create WindowProc, you must also return from the function using the ret macro (in small letters). RET generates a simple assembler command, not a macro instruction to exit WindowProc.


That was exactly the problem, i really appreciate your help on pointing that out, the program now runs as expected, thankyou.
Post 02 Jul 2026, 15:09
View user's profile Send private message Reply with quote
MаtQuasar



Joined: 22 Jun 2026
Posts: 11
MаtQuasar 02 Jul 2026, 15:12
Better save these registers on entry and restore them on exit, in WindowProc.

Code:
push    ebx esi edi    
Post 02 Jul 2026, 15:12
View user's profile Send private message Reply with quote
Byte_Blast



Joined: 01 Jul 2026
Posts: 5
Location: Australia
Byte_Blast 02 Jul 2026, 15:15
MаtQuasar wrote:
Better save these registers on entry and restore them on exit, in WindowProc.

Code:
push    ebx esi edi    


I was actually wondering this since it pushes those registers to the stack in the template file with the "uses" macroinstruction, but from what i understand and again, i am very new to this. The only reason to push those registers is if i end up using them again somewhere else in my program, and it's really just there to save them incase i forget i'm using them, is that correct?
Post 02 Jul 2026, 15:15
View user's profile Send private message Reply with quote
MаtQuasar



Joined: 22 Jun 2026
Posts: 11
MаtQuasar 02 Jul 2026, 15:30
Byte_Blast wrote:
MаtQuasar wrote:
Better save these registers on entry and restore them on exit, in WindowProc.

Code:
push    ebx esi edi    


I was actually wondering this since it pushes those registers to the stack in the template file with the "uses" macroinstruction, but from what i understand and again, i am very new to this. The only reason to push those registers is if i end up using them again somewhere else in my program, and it's really just there to save them incase i forget i'm using them, is that correct?


They are callee -saved register, rule in a function. But if you don't change these registers, I think it still work fine even if you don't preserve it. I too am beginner in Windows GUI programming, I end up using dialog box as GUI main window (DialogBoxParam API) for most of my hobby project as it is much easier - internal window message loop, we don't need to handle it ourselves.
Post 02 Jul 2026, 15:30
View user's profile Send private message Reply with quote
alCoPaUL



Joined: 20 Jun 2023
Posts: 11
Location: NYC
alCoPaUL 02 Jul 2026, 19:00
"First off, i just want to say that i am still relatively new to assembly programming...
.......
... i didn't bother to include any error control in my program because i can find the problem in WinDbg myself."

How can I ConDbg this?
Post 02 Jul 2026, 19:00
View user's profile Send private message Visit poster's website Reply with quote
Core i7



Joined: 14 Nov 2024
Posts: 170
Location: Socket on motherboard
Core i7 03 Jul 2026, 02:50
Why use the WinDbg kernel debugger in user mode? It's like shooting sparrows with a cannon. There's a universal one https://x64dbg.com/ , designed specifically for user applications in the ring(3). It's a powerful and convenient tool that supports many modern solutions—external plugins, scripts for automating the debugging process, etc. After calling each Win32API in your code, it automatically inserts its own GetLastError() in the background to display the error code in the register window.

You can write your own error checking routine — there's the GetLastError() fn for that (it simply returns the error code) and FormatMessage(), which converts the error code into a human-readable text equivalent. Here's an example of such a routine (use only in the debug version of the program):
Code:
proc  GetError  uses rax rbx rsi rdi
locals
   errMes  db  128 dup(0)
   errBuf  db  128 dup(0)
endl
        invoke  GetLastError
        push    rax
        invoke  FormatMessage,FORMAT_MESSAGE_FROM_SYSTEM,0,rax,0,addr errMes,128,0
        pop     rax
       cinvoke  wsprintf,addr errBuf,<'WinError:  0x%08X',10,'%s',0>,rax,addr errMes
        invoke  MessageBox,0,addr errBuf,0,0
        ret
endp

;//---- Now after any Win32API function, we call it like this: --------

        invoke  CreateFile,......   ; any API in the code
       stdcall  GetError            ;<------- check the result!
    
Post 03 Jul 2026, 02:50
View user's profile Send private message Reply with quote
Byte_Blast



Joined: 01 Jul 2026
Posts: 5
Location: Australia
Byte_Blast 03 Jul 2026, 13:47
Core i7 wrote:
Why use the WinDbg kernel debugger in user mode? It's like shooting sparrows with a cannon. There's a universal one https://x64dbg.com/ , designed specifically for user applications in the ring(3). It's a powerful and convenient tool that supports many modern solutions—external plugins, scripts for automating the debugging process, etc. After calling each Win32API in your code, it automatically inserts its own GetLastError() in the background to display the error code in the register window.

You can write your own error checking routine — there's the GetLastError() fn for that (it simply returns the error code) and FormatMessage(), which converts the error code into a human-readable text equivalent. Here's an example of such a routine (use only in the debug version of the program):
Code:
proc  GetError  uses rax rbx rsi rdi
locals
   errMes  db  128 dup(0)
   errBuf  db  128 dup(0)
endl
        invoke  GetLastError
        push    rax
        invoke  FormatMessage,FORMAT_MESSAGE_FROM_SYSTEM,0,rax,0,addr errMes,128,0
        pop     rax
       cinvoke  wsprintf,addr errBuf,<'WinError:  0x%08X',10,'%s',0>,rax,addr errMes
        invoke  MessageBox,0,addr errBuf,0,0
        ret
endp

;//---- Now after any Win32API function, we call it like this: --------

        invoke  CreateFile,......   ; any API in the code
       stdcall  GetError            ;<------- check the result!
    


I only use WinDbg solely because it was part of a course i took for Assembly programming and a section was covered on using WinDbg, hence why i used it.

I will have a look at x64Dbg, (x32Dbg in my case) i am also very new to debugging with a debugger as well. Again, when i say i am new to Assembly programming, i am talking about "I know enough to get me through most common obstacles", i don't have experience in programming at all before learning Assembly, so this is the only programming language i have chosen to learn, because i like the control as well as how verbose it is, just what i prefer.

I will probably need to watch some tutorials but i prefer a structured course that i can pay for when it comes to my self learning, if you have recommendations for some material i can read to instruct myself on debugging other than x64Dbgs documentation which i will read anyway, please don't hesitate to send me a private message.
Post 03 Jul 2026, 13:47
View user's profile Send private message Reply with quote
Core i7



Joined: 14 Nov 2024
Posts: 170
Location: Socket on motherboard
Core i7 03 Jul 2026, 15:02
WinDbg is currently the only kernel debugger available, and there's practically no replacement for it. Previously, there was the venerable SoftIce (which doesn't work on WinXP+) and Sysser from our Chinese friends (which doesn't work on Vista+). I've studied all three of these debuggers, but currently, I use WinDbg exclusively for examining drivers and the Win7+ kernel in general. It's a very powerful tool, but I'd like to point out that it's not designed for user applications.

As for Ring(3), x64Dbg is the leading x64 debugger here, replacing the 32-bit OllyDbg. All other tools are disassemblers, not debuggers, such as IDA-PRO, Ghidra, Radare, and many others. So, for 64-bit code, x64Dbg is the only one available, and there's no other replacement. If you have any specific debugging questions, please ask—you'll always find help here.
Post 03 Jul 2026, 15:02
View user's profile Send private message Reply with quote
AsmGuru62



Joined: 28 Jan 2004
Posts: 1812
Location: Toronto, Canada
AsmGuru62 04 Jul 2026, 12:04
The only issue is 'RET' instead of 'ret'.
TEMPLATE.ASM shipped with FASM has 'ret' and not 'RET'.
'uses ebx esi edi' is needed only if your 'WindowProc' uses (no pun!) these registers.
Post 04 Jul 2026, 12:04
View user's profile Send private message Send e-mail Reply with quote
Byte_Blast



Joined: 01 Jul 2026
Posts: 5
Location: Australia
Byte_Blast 05 Jul 2026, 13:44
AsmGuru62 wrote:
The only issue is 'RET' instead of 'ret'.
TEMPLATE.ASM shipped with FASM has 'ret' and not 'RET'.
'uses ebx esi edi' is needed only if your 'WindowProc' uses (no pun!) these registers.


Thankyou for pointing out the typo but it was already pointed out by macomics.

I use Notepad++ as my text editor, and i have changed my language defaults to make all instructions be capitalized because i like the style of that more than lowercase.

I have however fixed the capitalization of ret in my preferences so it will now be lowercase from now on.

Also, thankyou for also explaining the uses macroinstruction to me.
Post 05 Jul 2026, 13:44
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-2026, Tomasz Grysztar. Also on GitHub, YouTube.

Website powered by rwasa.