flat assembler
Message board for the users of flat assembler.
Index
> Windows > Why is creating a window so incredibly frustrating. |
| Author |
|
|
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.
|
|||||||||||
|
|
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. |
|||
|
|
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. |
|||
|
|
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 |
|||
|
|
Byte_Blast 02 Jul 2026, 15:15
MаtQuasar wrote: Better save these registers on entry and restore them on exit, in WindowProc. 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? |
|||
|
|
MаtQuasar 02 Jul 2026, 15:30
Byte_Blast wrote:
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. |
|||
|
|
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? _________________ Assembly Language Quines https://bitbucket.org/alcopavl/ia-64_quine/src/main/ https://bitbucket.org/alcopavl/x86x64/src/main/ https://github.com/alcopaul/beth_GviLLErMo_GIMO |
|||
|
|
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! |
|||
|
|
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. 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. |
|||
|
|
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. |
|||
|
|
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. |
|||
|
|
Byte_Blast 05 Jul 2026, 13:44
AsmGuru62 wrote: The only issue is 'RET' instead of 'ret'. 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. |
|||
|
< Last Thread | Next Thread > |
Forum Rules:
|
Copyright © 1999-2026, Tomasz Grysztar. Also on GitHub, YouTube.
Website powered by rwasa.