Need help getting my window on screen. Masm64

Started by Sarel, April 13, 2011, 04:21:05 PM

Previous topic - Next topic

Sarel

I am trying to get a simple window on screen. It is based on Iczelion's no 3 tutorial. Currently it is assembling and linking but not showing on screen. I need to use taskmanager to stop the process.

;ml64 /c Window.asm
;link /entry:Main /subsystem:windows /machine:x64 /libpath:c:\masm64\lib window.obj

option casemap:none

includelib \masm64\lib\user32.lib            ; calls to functions in user32.lib and kernel32.lib
includelib \masm64\lib\kernel32.lib

externdef MessageBoxA : near
externdef ExitProcess : near
externdef GetModuleHandleA : near
externdef LoadIconA : near
externdef LoadCursorA : near
externdef CreateWindowExA : near
externdef ShowWindow : near
externdef UpdateWindow : near
externdef GetMessageA : near
externdef RegisterClassExA : near
externdef TranslateMessage : near
externdef DispatchMessageA : near
externdef PostQuitMessage : near
externdef DefWindowProcA : near


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

CS_VREDRAW                           equ 1h
CS_HREDRAW                           equ 2h
COLOR_WINDOW                         equ 5
IDI_APPLICATION                      equ 32512
IDC_ARROW                            equ 32512
WS_CAPTION                           equ 0C00000h
WS_OVERLAPPED                        equ 0h
WS_SYSMENU                           equ 80000h
WS_THICKFRAME                        equ 40000h
WS_MINIMIZEBOX                       equ 20000h
WS_MAXIMIZEBOX                       equ 10000h
WS_OVERLAPPEDWINDOW                  equ WS_OVERLAPPED OR WS_CAPTION OR WS_SYSMENU OR WS_THICKFRAME OR WS_MINIMIZEBOX OR WS_MAXIMIZEBOX
CW_USEDEFAULT                        equ 80000000h
NULL                                 equ 0
WM_CREATE                            equ 1h
WM_DESTROY                           equ 2h
SW_SHOWDEFAULT                       equ 10



MESSAGE STRUCT
hwnd            dq 0
message         dd 0
                dd 0    ;Padding
wParam          dq 0
lParam          dq 0
time            dd 0
x               dd 0    ;POINT structure x
y               dd 0    ;POINT structure y
                dd 0    ;Padding
MESSAGE ENDS


WNDCLASSEX STRUCT
cbSize        DD 0    ;+0h Size of this structure
style         DD 0    ;+4h window class style
lpfnWndProc   DQ 0    ;+8h pointer to Window Procedure
cbClsExtra    DD 0    ;+10h no. of extra bytes to allocate after structure
cbWndExtra    DD 0    ;+14h no. of extra bytes to allocate after window instance
hInstance     DQ 0    ;+18h handle to instance containing window procedure
hIcon         DQ 0    ;+20h handle to the class icon
hCursor       DQ 0    ;+28h handle to the class cursor
hbrBackground DQ 0    ;+30h identifies the class background brush
lpszMenuName  DQ 0    ;+38h pointer to resource name for class menu
lpszClassName DQ 0    ;+40h pointer to string for window class name
hIconSm       DQ 0    ;+40h handle to the small icon
WNDCLASSEX ENDS



.DATA
wc              WNDCLASSEX <>
hWnd            dq 0
msg             MESSAGE <>
ClassName db "SimpleWinClass",0,0       ; the name of our window class
AppName   db "OurFirstWindow",0,0       ; the name of our window


;-----------------------------------------------------------------------------------------
.CODE                   ; Here begins our code
Main proc

;Get instance handle
    mov rcx,0h
    sub rsp,8
    call GetModuleHandleA            ; get the instance handle of our program.
    add rsp,8
;Fill wc   
    mov wc.hInstance,rax
    mov wc.cbSize,SIZEOF WNDCLASSEX              ;fill values in members of wc
    mov wc.style, CS_HREDRAW or CS_VREDRAW
    lea rax,WndProc
    mov wc.lpfnWndProc,rax                       ;ADDR WndProc
    mov wc.cbClsExtra,0
    mov wc.cbWndExtra,0
    mov wc.hbrBackground,COLOR_WINDOW+1
    mov wc.lpszMenuName,0
    lea rax,ClassName
    mov wc.lpszClassName,rax                     ;OFFSET ClassName
   
    mov rdx,IDI_APPLICATION
    mov rcx,NULL
    sub rsp,10h
    call LoadIconA                               ;invoke LoadIcon,NULL,IDI_APPLICATION
    add rsp,10h
    mov wc.hIcon,rax
    mov wc.hIconSm,rax
   
    mov rdx,IDC_ARROW
    mov rcx,NULL
    sub rsp,10h
    call LoadCursorA                             ;invoke LoadCursor,NULL,IDC_ARROW
    add rsp,10h
    mov wc.hCursor,rax


;Register the class
    lea rcx,wc
    sub rsp,8h
    call RegisterClassExA                        ;invoke RegisterClassEx,addr wc
    add rsp,8h


;Create our window
    push NULL
    push wc.hInstance
    push NULL
    push NULL
    push CW_USEDEFAULT
    push CW_USEDEFAULT
    push CW_USEDEFAULT
    push CW_USEDEFAULT
    mov r9,WS_OVERLAPPEDWINDOW
    lea r8,AppName
    lea rdx,ClassName
    mov rcx,NULL
    sub rsp,60h
    call CreateWindowExA
    add rsp,60h
    mov hWnd,rax


;Show our window
    mov rdx,SW_SHOWDEFAULT
    mov rcx,hWnd
    sub rsp,10h
    call ShowWindow             ;invoke ShowWindow, hwnd,CmdShow
    add rsp,10h
   

;Update the window
    mov rcx,hWnd
    sub rsp,8h
    call UpdateWindow           ;invoke UpdateWindow, hwnd
    add rsp,8h
   
   
  NextMessage:
;Call GetMessageA
    mov r9,0
    mov r8,0
    mov rdx,NULL
    lea rcx,msg
    sub rsp,28h
    call GetMessageA
    add rsp,28h
;Quit if return value is 0
    cmp rax,0
    je EndMessage
;Call TranslateMessage   
    lea rcx,msg
    sub rsp,8h
    call TranslateMessage                       ;invoke TranslateMessage, ADDR msg
    add rsp,8h
;call DispatchMessageA
    lea rcx,msg
    sub rsp,8h
    call DispatchMessageA                       ;invoke DispatchMessage, ADDR msg
    add rsp,8h
;Get new message
    jmp NextMessage

   
   EndMessage:
    mov rcx,msg.wParam                          ; return exit code in ecx
    call ExitProcess

    ret

Main endp
;-----------------------------------------------------------------------------------------
;-----------------------------------------------------------------------------------------


    WndProc proc    ;For 64bit

;Save parameters that is in registers on the stack.
    ;[rsp+0] = return address
    mov [rsp+8h],rcx
    mov [rsp+10h],rdx
    mov [rsp+18h],r8
    mov [rsp+20h],r9
    push rbp
    mov rbp,rsp         ;[rbp+0] = old rbp value,
                        ;[rbp+8h] = return addr,
                        ;[rbp+10h] = rcx = hwnd
                        ;[rbp+18h] = rdx = message :uMSG
                        ;[rbp+20h] = r8 = wParam
                        ;[rbp+28h] = r9 = lParam
   
    cmp qword ptr[ebp+18h],WM_DESTROY
    je QuitPlease
    cmp qword ptr[ebx+18h],WM_CREATE
    je Do_Create
   
    xor rcx,rcx
    sub rsp,8h
    call PostQuitMessage
    add rsp,8h
    xor rax,rax
    ret
  QuitPlease:
    ;rcx, rdx, r8 and r9 already contain hwnd, message, wparam and lparam
    call DefWindowProcA
    ret
  Do_Create:
    ;Dosomethig
    xor rax,rax
    ret

WndProc endp   


end


dedndave

my mistake - you are trying to write a 64-bit program
Iczelion's examples are 32-bit
you are including, for example, kernel32.inc and lib
which are for 32-bit programs   :P

also - Iczelion's tutorials are out of date
modern include packages take care of the API prototypes, standard constant defintions, and so on

i think i would start by getting a 32-bit app running, then have a look in the 64-bit forum for some modern code examples

but, you are mixing apples and oranges, as it is

Sarel

I have made a 32 bit program first and it works. Then I changed all invokes to calls and adapted for 64 bit. I have made all relevant structures and equates for 64 bit. What I dont understand is that my windows\system directory is empty but my windows\system32 directory has the user32.dll and kernel32.dll. These are the dll's i am using. There is also a windows\syswow64 directory with the files in, but these do not work. I am also wondering why its even called user32 and kernel32. Why not user64 and kernel64. Any way, I have read a lot of things for GoAsm and it certainly looks the way to go. Excellent information with the GoAsm assembler. But first I want to finish what I have started. I want a clear straight forward example with preferably no procedures or jumping around. Definately nothing in it that is automatically generated for me or taken care of for me. I want to understand how it works. Thanks to GoAsm I do have an Idea

dedndave

let me start off by saying - i do not write 64-bit code   :P
there are others that can offer a clearer solution

however, i believe that there is a 64-bit set of includes and import libraries - seperate from the 32-bit
you might want to visit japheth's site to get a set of 64-bit stuff   :bg
his download includes a set of batch files for building the import libraries...

http://japheth.de/WinInc.html

one other note
a "more correct" sub-forum would be
http://www.masm32.com/board/index.php?board=43.0
you will find a lot more useful info there

qWord

Sarel,

It is really recommendable to use japhets jWasm and WinInc. jWasm allowes you to use the well known highlevel syntax (invoke,.if,.while,...).

qWord
FPU in a trice: SmplMath
It's that simple!

hasanbacioglu

Quote from: Sarel on April 13, 2011, 06:34:38 PM
I have made a 32 bit program first and it works. Then I changed all invokes to calls and adapted for 64 bit. I have made all relevant structures and equates for 64 bit. What I dont understand is that my windows\system directory is empty but my windows\system32 directory has the user32.dll and kernel32.dll. These are the dll's i am using. There is also a windows\syswow64 directory with the files in, but these do not work. I am also wondering why its even called user32 and kernel32. Why not user64 and kernel64. Any way, I have read a lot of things for GoAsm and it certainly looks the way to go. Excellent information with the GoAsm assembler. But first I want to finish what I have started. I want a clear straight forward example with preferably no procedures or jumping around. Definately nothing in it that is automatically generated for me or taken care of for me. I want to understand how it works. Thanks to GoAsm I do have an Idea

Hi Sarel,

  I strongly suggest that you visit following link and read whole article to get an idea about why user32.dll and kernel32.dll exist under windows/system32 directory. (Maybe they don't) ! Just in case you may wanna have a quick look at it, I'll paste the most relevant part.
                 
                          http://msdn.microsoft.com/en-us/magazine/cc300794.aspx

    While running a fully 64-bit Windows system sounds great, the reality is that you'll very likely need to run Win32 code for a while. Towards that end, x64 versions of Windows include the WOW64 subsystem that lets Win32 and Win64 processes run side-by-side on the same system. However, loading your 32-bit DLL into a 64-bit process, or vice versa, isn't supported. (It's a good thing, trust me.) And you can finally kiss good bye to 16-bit legacy code!
In x64 versions of Windows, a process that starts from a 64-bit executable such as Explorer.exe can only load Win64 DLLs, while a process started from a 32-bit executable can only load Win32 DLLs. When a Win32 process makes a call to kernel mode—to read a file, for instance—the WOW64 code intercepts the call silently and invokes the correct x64 equivalent code in its place.
Of course, processes of different lineages (32-bit versus 64-bit) need to be able to communicate with each other. Luckily, all the usual interprocess communication mechanisms that you know and love in Win32 also work in Win64, including shared memory, named pipes, and named synchronization objects.
You might be thinking, "But what about the system directory? The same directory can't hold both 32- and 64-bit versions of system DLLs such as KERNEL32 or USER32, right?" WOW64 magically takes care of this for you by the doing selective file system redirection. File activity from a Win32 process that would normally go to the System32 directory instead goes to a directory named SysWow64. Under the covers, WOW64 silently changes these requests to point at the SysWow64 directory. A Win64 system effectively has two \Windows\System32 directories—one with x64 binaries, the other with the Win32 equivalents.
Smooth as it may seem, this can be confusing. For instance, I was at one point using (unbeknownst to me) a 32-bit command-line prompt. When I ran DIR on Kernel32.dll in the System32 directory, I got the exact same results as when I did the same thing in the SysWow64 directory. It took a lot of head scratching before I figured out that the file system redirection was working just like it should. That is, even though I thought I was working in the \Windows\System32 directory, WOW64 was redirecting the calls to the SysWow64 directory. Incidentally, if you really do want to get at the 32-bit \Windows\System32 directory from an x64 app, the GetSystemWow64Directory API gives you the correct path. Be sure to read the MSDN® documentation for the complete story.
Beyond file system redirection, another bit of magic performed by WOW64 is registry redirection. Consider my earlier statement about Win32 DLLs not loading into Win64 processes, and then think about COM and its use of the registry to load in-process server DLLs. What if a 64-bit application uses CoCreateInstance to create an object that's implemented in a Win32 DLL? The DLL can't load, right? WOW64 saves the day again by redirecting access from 32-bit applications to the \Software\Classes (and related) registry nodes. The net effect is that Win32 applications have a different (but mostly parallel) view of the registry than x64 applications. As you'd expect, the OS provides an escape hatch for 32-bit applications to read the actual 64-bit registry value by specifying new flag values when calling RegOpenKey and friends.

Regards,


mineiro

Hello Sr Sarel, I have analyzed your example and appears to me that you are not reserving space to "shadow space".
If your function uses or not 4 arguments, you need reserve some stack space (shadow space)(add/sub rsp,4*8).
I'm currently playing with 64 bits now, and I can suggest to you to do not put the "pads" inside structures (more chances to errors), it is more easy if you align the structure to 8. You have the option to align all of these structures in command line with "/Zp8" for example, but do not do this, because in my tests, some structures do not be aligned to this value.
In the moment that your code call another function, the stack pointer needs be aligned to a multiple of 16, or in others words, rsp=???????0. Well, the first thing that comes in mind is put a "sub rsp,8" in the start of your procedure, but in my tests this is not a good choice, so you can put "and rsp,-10h" and this works.
About masm 64 , you can put an "ALIAS <WinMainCRTStartup>=<entrypoint>", so you can forget about command line "/entry:entrypoint".
If you will mount examples inside some editor, like Radasm, do not choose the menu "make, go", because radasm or others editors are done to work(launch) with 32 bits. I have coded one example and it worked fine when I put "make,go", so I have restarted my machine and when I go to explorer and clicked the example , they do not have worked. So, keep this in mind. If you use some editor to help you while coding, only assemble and compile, but do not click in "go" button or menu. Execute the program or using windows explorer or console.
Follows a simple window example, based in the same tutorials that you are getting as a base.

Sarel

Mineiro, this is great. I had a quick look and I can follow the program and how parrameters are passed. I need time to let it sink in. Sorry for the long absence, I was quite fed up. :bg