News:

Masm32 SDK description, downloads and other helpful links
Message to All Guests
NB: Posting URL's See here: Posted URL Change

Main Menu

Win32 My First Window

Started by tda0626, April 24, 2024, 11:05:19 AM

Previous topic - Next topic

TimoVJL

Quote from: C3 on April 27, 2024, 08:29:15 PMOr then I am just too lazy to change the entry point in Visual Studio and use what it defaults in Assembly Builds.

There is also default entry point for Console Projects in Visual Studio.
I also use those linker's default function names, as link.exe and polink.exe knows them.
May the source be with you

tda0626

Quote from: TimoVJL on April 27, 2024, 12:42:51 PMIf you don't need commandline, just forget a whole that WinMain and create window in normal way.
As many of these site users can tell, WinMain don't belong to asm world.
Commandline processing is just own story and some of can give details for that, like Vortex.
Naturally i can provide that in C language, as know how avoid crt.



I was going by the tutorial so wanted to follow it verbatim.



Pulled up my program in a debugger, x32dbg, to see if I saw anything that looked suspicious but didn't find anything. Not sure what is going on...

zedd151

Quote from: tda0626 on April 27, 2024, 11:05:20 PMI was going by the tutorial so wanted to follow it verbatim.
....
Pulled up my program in a debugger, x32dbg, to see if I saw anything that looked suspicious but didn't find anything. Not sure what is going on...

Are you sure that you haven't missed anything during conversion, assuming you converted it from 'invoke' to 'push/push... call'? ( Is your current project iczelions tutorial #3?)

And pushed the parameters in the correct order?

And have the correct number of parameters pushed to the stack? (For a given call)

Tip: You can post your attachment in your next post. Not necessary to keep using the first post, it could get overlooked if attached there. Seems I was the only one that downloaded the last attachment. (At the time of this post, downloads = 1)

Besides when posting your code sequentially within your posts (instead of overwriting previous attachments) you have a record of the progress of your project. As well as making it easier for those that are following your progress.
When the project is completed and bug free, you can always remove the older attachments since they would be no longer needed. My point of view.

zedd151

#48
Iczelions tutorial #3 my conversion from 'invoke' syntax to 'push/call' syntax. Compare that with your own code, tda0626.  :smiley:

.386
.model flat,stdcall
option casemap:none
include \masm32\include\windows.inc
include \masm32\include\user32.inc
include \masm32\include\kernel32.inc
includelib \masm32\lib\user32.lib
includelib \masm32\lib\kernel32.lib

WinMain proto :DWORD,:DWORD,:DWORD,:DWORD

.data
ClassName db "SimpleWinClass",0
AppName  db "Our First Window",0

.data?
hInstance dd ?
CommandLine dd ?

.code
start:
    push 0
    call GetModuleHandle
    mov    hInstance,eax
   
    call GetCommandLine
    mov  CommandLine,eax
   
    push SW_SHOWDEFAULT
    push CommandLine
    push 0
    push hInstance
    call WinMain
   
    push eax
    call ExitProcess

WinMain proc hInst:HINSTANCE, hPrevInst:HINSTANCE, CmdLine:LPSTR, CmdShow:DWORD
LOCAL wc:WNDCLASSEX, msg:MSG, hwnd:HWND
   
    mov   wc.cbSize, SIZEOF WNDCLASSEX
    mov   wc.style, CS_HREDRAW or CS_VREDRAW
    mov   wc.lpfnWndProc, OFFSET WndProc
    mov   wc.cbClsExtra, NULL
    mov   wc.cbWndExtra, NULL
    push  hInstance
    pop   wc.hInstance
    mov   wc.hbrBackground, COLOR_WINDOW+1
    mov   wc.lpszMenuName, NULL
    mov   wc.lpszClassName, OFFSET ClassName

    push IDI_APPLICATION
    push 0
    call LoadIcon
    mov   wc.hIcon, eax
    mov   wc.hIconSm, eax
   
    push IDC_ARROW
    push 0
    call LoadCursor
    mov   wc.hCursor, eax
   
    lea eax, wc
    push eax
    call RegisterClassEx
   
    push 0
    push hInst
    push 0
    push 0
    push CW_USEDEFAULT
    push CW_USEDEFAULT
    push CW_USEDEFAULT
    push CW_USEDEFAULT
    push WS_OVERLAPPEDWINDOW
    push offset AppName
    push offset ClassName
    push 0
    call CreateWindowEx
    mov   hwnd, eax
   
    push SW_SHOWNORMAL
    push hwnd
    call ShowWindow
   
    push hwnd
    call UpdateWindow
    .WHILE TRUE
   
        push 0
        push 0
        push 0
        lea eax, msg
        push eax
        call GetMessage
       
    .BREAK .IF (!eax)
   
        lea eax, msg
        push eax
        call TranslateMessage
       
        lea eax, msg
        push eax
        call DispatchMessage
       
    .ENDW
    mov     eax,msg.wParam
    ret
WinMain endp

WndProc proc hWnd:HWND, uMsg:UINT, wParam:WPARAM, lParam:LPARAM
    .if uMsg==WM_DESTROY
   
        push 0
        call PostQuitMessage
       
    .else
   
        push lParam
        push wParam
        push uMsg
        push hWnd
        call DefWindowProc
            
        ret
    .endif
   
    xor eax,eax
    ret
WndProc endp

end start

sinsi

Quote from: TimoVJL on April 27, 2024, 12:42:51 PMIf you don't need commandline, just forget a whole that WinMain and create window in normal way.
As many of these site users can tell, WinMain don't belong to asm world.
Agreed.

    .else   
        push lParam
        push wParam
        push umsg
        push hWnd
        call DefWindowProc
    .endif
          xor eax, eax ;<<<<<<<<< this will ALWAYS return 0, not a good thing
    ret

tda0626

Quote from: sudoku on April 28, 2024, 12:46:55 AMIczelions tutorial #3 my conversion from 'invoke' syntax to 'push/call' syntax. Compare that with your own code, tda0626.  :smiley:

Awesome! I made some minor modifications to my code based of yours and now it runs and exits without a hitch! The call to CreateWindow now returns a value in EAX when before it was returning zero.  :eusa_clap:

Now I will convert it over to invoke statements to shorten it.

Thank you for the help!


zedd151

Quote from: tda0626 on April 28, 2024, 02:05:31 AMI made some minor modifications to my code based of yours and now it runs and exits without a hitch!
...
Now I will convert it over to invoke statements to shorten it.
Great!  :thumbsup:

Quote from: tda0626 on April 28, 2024, 02:05:31 AMThank you for the help!
No problem.  :smiley:

Converting the code as I did, is often error prone itself. I had to make several corrections while converting it (due to my own errors). I hope that I won't have to do that again any time soon, especially with larger projects.  :greensml:

tda0626

2 questions still:

Running the program in debugger, I noticed that my jnz code is jne. Are these the same thing?

Could you explain a little bit in detail what is happening here and why we use msg.wParam?

mov eax,msg.wParam

I am assuming the wParam is storing the return values of a message. That is how I am reading it.


Tim

NoCforMe

1. JNZ == JNE (just as JZ == JE)**. They're just assembler synonyms.

2. MSG is a structure, and wParam is one of its members. Not sure why that's being used as the source of the return value from WinMain(), but apparently Iczelion had his reasons for doing that.

BTW, the only time you care what an executable program returns (as that return value from WinMain()) is when you're running a program from a batch file and need to check its return status. Otherwise, as suggested above, don't bother with the whole WinMain() business, which is really for C and other higher-level languages. It's a needless construct in assembly.

** HOWEVER: JB/JBE is not the same as JL/JLE, and JA/JAE is not the same as JG/JGE. One set is for unsigned comparisons, the other for signed. Be sure you use the right one!
Assembly language programming should be fun. That's why I do it.

zedd151

Quote from: tda0626 on April 28, 2024, 02:41:56 AM2 questions still:

Running the program in debugger, I noticed that my jnz code is jne. Are these the same thing?
Yes. jnz = Jump if not zero (result of a comparison)
    jne = Jump if not equal(result of a comparison)

The debuggers do that, but only for instructions that are equivalent. ollydbg does the same.
Quote from: tda0626 on April 28, 2024, 02:41:56 AMCould you explain a little bit in detail what is happening here and why we use msg.wParam?

mov eax,msg.wParam
I am assuming the wParam is storing the return values of a message. That is how I am reading it.
More specifically, msg.wParam is the wParam part of the MSG structure
From win32.hlp...
The MSG structure contains message information from a thread's message queue.

typedef struct MSG {    // msg 
    HWND  hwnd;   
    UINT  message;
    WPARAM wParam;
    LPARAM lParam;
    DWORD  time;
    POINT  pt;
} MSG;
Members:

hwnd
Identifies the window whose window procedure receives the message.

message
Specifies the message number.

wParam
Specifies additional information about the message. The exact meaning depends on the value of the message member.

lParam
Specifies additional information about the message. The exact meaning depends on the value of the message member.

time
Specifies the time at which the message was posted.

pt
Specifies the cursor position, in screen coordinates, when the message was posted.

sinsi

Quote from: tda0626 on April 28, 2024, 02:05:31 AMThe call to CreateWindow now returns a value in EAX when before it was returning zero.
But do you know why? There were (I think) two problems with your latest code, neither of which were because you weren't using invoke

tda0626

Quote from: sinsi on April 28, 2024, 03:51:57 AM
Quote from: tda0626 on April 28, 2024, 02:05:31 AMThe call to CreateWindow now returns a value in EAX when before it was returning zero.
But do you know why? There were (I think) two problems with your latest code, neither of which were because you weren't using invoke


I am not so sure why it works now and not before. I only changed a few lines of code per sudoku's code. Can you give me a rundown on the two problems that were in it?


Quote from: sudoku on April 28, 2024, 03:08:40 AMMore specifically, msg.wParam is the wParam part of the MSG structure
From win32.hlp...

I understand that piece but why return the value? Is wParam a return value from a message?

NoCforMe

Quote from: sudoku on April 28, 2024, 03:08:40 AMYes. jnz = Jump if not zero (result of a comparison)
    jne = Jump if not equal(result of a comparison)

Hmm, is there an echo in here?
Assembly language programming should be fun. That's why I do it.

zedd151

Quote from: tda0626 on April 28, 2024, 04:18:02 AM
Quote from: sudoku on April 28, 2024, 03:08:40 AMMore specifically, msg.wParam is the wParam part of the MSG structure
From win32.hlp...
I understand that piece but why return the value? Is wParam a return value from a message?

Short answer, idunno for certain. Convention?
Longer answer via Google search...
https://www.gamedev.net/forums/topic/121603-why-must-return-msgwparam/
and another...
https://cplusplus.com/forum/windows/103120/
... still another
https://forums.codeguru.com/showthread.php?497342-Significance-of-return-
and ...
https://learn.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-winmain
I learned a little bit from those, although mostly they are geared towards c/c++ programmers it seems.

Quote from: NoCforMe on April 28, 2024, 04:20:33 AMHmm, is there an echo in here?
No.
I was preparing my post, while you were posting. (I'm slow)

NoCforMe

Some general advice to the OP here (and remember that this is free advice which you are free to take or ignore):

Since you're an asm beginner, don't copy code that you don't understand and try to make it work. If you're looking at someone's code (C, asm, doesn't matter), make sure you understand what it does and how it works before trying to implement it yourself. Otherwise you'll just be trying this and trying that, maybe getting it to work but still not understanding why it works.

This is important. If you look at some code and can't understand what it does, pick it apart piece by piece. Look up the functions, messages and structures on Microsoft's documentation site, Microsoft Learn, and pay attention to the descriptions there.

Or ask here. As you can see, plenty of folks ready to help you.

End of advice.
Assembly language programming should be fun. That's why I do it.