I don't know much about nasm and win32 programming, I think that masm is far easier, because of all the macros. But I want to know how the code in this tutorial will look like in nasm syntax. Can somebody please help me with this?
http://spiff.tripnet.se/~iczelion/tut3.html
Posted on 2004-12-23 08:41:23 by dev_zero
The more easy way to do, is to use nagoa package (there are some examples there) and in some way can look a little like masm :shock:

If you use another alternative, should be a little more dificult (specially for the include files), you can use -fwin32 for link the object file with lcc or link (yes the one that comes with masm32 package) also check this site out http://alink.sourceforge.net

This little example work for both of them:


extern _MessageBoxA@16
extern _ExitProcess@4

global _WinMain@16
segment .data use32 class=data
hola db "hola mundo", 0

segment .text USE32 class=code
_WinMain@16:
push dword 0
push dword hola
push dword hola
push dword 0
call _MessageBoxA@16
push dword 0
call _ExitProcess@4

nasm -fwin32 name.asm
lcclnk -s -subsystem windows name.obj
or
link /entry:WinMain /subsystem:windows /libpath:c:\masm32\lib user32.lib kernel32.lib name.obj



But the output is diferent ;), lcc insert a initialization code, for example in the examples showed by icz, there is a entry point named start, then he do the setup of the command line, the module handle, this code and a little more is inserted by lcclnk (I guess there is a option for not do that, but havent watched the help ;)), with link, there is no insertion of startup code, then you can make the setup like is done in the icz examples.


The main problem, is that aparently the include files out there are not completely compatible (I guess they insert some extra things that garbage the output :)).

In that way, the nagoa package is more usable and stable, by the way you can plug it to radasm ;), in that package there are some examples how is used that include file.


There is a group for help in yahoo win32-nasm-users, altought I dont like the interface and the publicity I will prefer a board :P.
Posted on 2004-12-23 14:41:09 by rea
The thing is, that I wanted to see and learn how the WinMain and WndProc procedure without the macros would look like in nasm syntax. And how I can initialize the WNDCLASSEX structure in nasm sytax..
Posted on 2004-12-23 15:11:06 by dev_zero
This example will work with: nasmw -fwin32 name.asm and then: link /entry:Entry /subsystem:windows /libpath:c:\masm32\lib user32.lib kernel32.lib name.obj

There is a problem if you try include directly nagoa.inc :), I supose that is related to some macros added there (pheraphs the problem is to include pemac when in some way is something diferent), is for that I include the definitions of the structs, equates used and because you only have whanted (whas the most dificult part.. lol), because you only whanted to know how to setup a function, I add also a macro apicall for let me type more easy all the push dword :), the first callings are done manually, that is pushing in reverse order and then calling the function like is defined in the library _name@sizeInBytesOfArguments


This structures are extracted from nagoa.inc (I should see what is the problem and correct it.. ;))
STRUC WNDCLASSEX

.cbSize RESD 1
.style RESD 1
.lpfnWndProc RESD 1
.cbClsExtra RESD 1
.cbWndExtra RESD 1
.hInstance RESD 1
.hIcon RESD 1
.hCursor RESD 1
.hbrBackground RESD 1
.lpszMenuName RESD 1
.lpszClassName RESD 1
.hIconSm RESD 1
ENDSTRUC

STRUC POINT
.x RESD 1
.y RESD 1
ENDSTRUC

STRUC MSG
.hwnd RESD 1
.message RESD 1
.wParam RESD 1
.lParam RESD 1
.time RESD 1
.pt RESB POINT_size
ENDSTRUC

%define SW_SHOWDEFAULT 10
%define CS_VREDRAW 0x0001
%define CS_HREDRAW 0x0002
%define COLOR_WINDOW 5
%define IDI_APPLICATION 32512
%define IDC_ARROW 32512
%define CW_USEDEFAULT 80000000h

%define WS_OVERLAPPED 0x00000000
%define WS_CAPTION 0x00C00000
%define WS_SYSMENU 0x00080000
%define WS_THICKFRAME 0x00040000
%define WS_MINIMIZEBOX 0x00020000
%define WS_MAXIMIZEBOX 0x00010000
%define WS_OVERLAPPEDWINDOW (WS_OVERLAPPED | \
WS_CAPTION | \
WS_SYSMENU | \
WS_THICKFRAME | \
WS_MINIMIZEBOX | \
WS_MAXIMIZEBOX)
%define WM_DESTROY 2h


A simple macro that will let me type less (a little lazy), push the n-1 arguments to the macro in reverse order and call the decored function that contain apart from the name a "_" prefix and a @sizeOfbytesOfArguments also declare the name like extern (defined somewhere else.. a mark for the linker)


%macro apicall2 2
extern _%1@%2
call _%1@%2
%endmacro

%macro apicall 1-*
%assign %%n %0-1
%rep %%n
%rotate -1
push dword %1
%endrep
%rotate -1
%assign %%n %%n*4
apicall2 %1, %%n
%endmacro


I will do some manual calling (the more easy functions ;)) then I declare them also manually like extern with the decorated name.


extern _GetModuleHandleA@4
extern _GetCommandLineA@0
extern _ExitProcess@4



definition of segments (code, data, bss) see that you use resX (reserve X n times: resX n) instead of dd (declare double)


segment .data use32 class=data
ClassName db "SimpleWindClass", 0
AppName db "Our first Window? :P", 0

segment .bss use32 class=bss
hInstance resd 1
CommandLine resd 1


segment .text USE32 class=code


Here I make the name more explicit, because we will use link that dosent insert automatically initialization like lcclnk do.



global _Entry
_Entry:

The initialization part (this one is the inserted be lcclnk), also you can see how you push and call decorated names (they are previously declared as externs)


push dword 0
call _GetModuleHandleA@4
mov [hInstance], eax
call _GetCommandLineA@0
mov [CommandLine], eax
push dword SW_SHOWDEFAULT
push CommandLine
push dword 0
push dword[hInstance]
call WinMain
push eax
call _ExitProcess@4


Here we setup a stack frame, if yu see the defines, you see that I put them after push ebp and mov ebp, esp because after that point is where they have the meaning that Im giving. For example, if you dont do the stack frame (the secuence of push and mov over ebp and esp) then, you will be refering to the arguments of the anterior call...

Also you can see how is allocated some space in the stack for the local vars, also the definitions of the names are I put them after sub esp, nBytes, because is after that point they obtain the real meaning that Im giving to them.


WinMain:
push ebp
mov ebp, esp
%define SavedEBP ebp
%define SavedRetAddress ebp+4
%define hInst ebp+8
%define hPrevInst ebp+12
%define CmdLine ebp+16
%define CmdShow ebp+20
sub esp, WNDCLASSEX_size+MSG_size+4
%define hwnd ebp- (WNDCLASSEX_size+MSG_size+4)
%define msg ebp- (WNDCLASSEX_size+MSG_size)
%define wnd ebp- (WNDCLASSEX_size)


Here is how you fill a structure in memory, you see, you need specify the size of the movement only if there is no a precense of a register, because the register give the size of the movement or push...., by the way, nasm dosent suport structs, They are used with a macro (struc) and in some way, the work is define names that are composed by the name of the struct point member of the struct, is for that you use wnd+WNDCLASSEX.cbSize, let analyze a little example:

STRUC POINT
.x RESD 1
.y RESD 1
ENDSTRUC
Here are defined some things:
POINT equ 0
POINT_size contain the size of the struct
POINT.x equ 0
POINT.y equ 4

Altough they are not equates, but make sense ;)...
Then if you have a label (a addres in memory) and then you sum a x number, you are accesing a offset from than start address, dont know if I explain well, but that is what the structs are models for access memory and be the way provide a meaning... then mov eax, will be translated to diferent things, depending of what is p a address in the data section or in the stack section....


mov dword[wnd+WNDCLASSEX.cbSize], WNDCLASSEX_size
mov dword[wnd+WNDCLASSEX.style], CS_VREDRAW|CS_HREDRAW
mov dword[wnd+WNDCLASSEX.lpfnWndProc], WndProc
mov dword[wnd+WNDCLASSEX.cbClsExtra], 0
mov dword[wnd+WNDCLASSEX.cbWndExtra], 0
mov eax, [hInst]
mov [wnd+WNDCLASSEX.hInstance], eax
mov dword[wnd+WNDCLASSEX.hbrBackground], COLOR_WINDOW+1
mov dword[wnd+WNDCLASSEX.lpszMenuName], 0
mov dword[wnd+WNDCLASSEX.lpszClassName], ClassName
apicall LoadIconA, 0, IDI_APPLICATION
mov [wnd+WNDCLASSEX.hIcon], eax
mov [wnd+WNDCLASSEX.hIconSm], eax
apicall LoadCursorA, 0, IDC_ARROW
mov dword[wnd+WNDCLASSEX.hCursor], eax
lea eax, [wnd]
apicall RegisterClassExA, eax
apicall CreateWindowExA, 0, ClassName, AppName, WS_OVERLAPPEDWINDOW,\
CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,\
0, 0, [hInstance], 0
mov [hwnd], eax
apicall ShowWindow, [hwnd], [CmdShow]
apicall UpdateWindow, [hwnd]
.again:
lea eax, [msg]
apicall GetMessageA, eax, 0, 0, 0
cmp eax, 0
je .end
lea eax, [msg]
apicall TranslateMessage, eax
lea eax, [msg]
apicall DispatchMessageA, eax
jmp .again
.end:
mov eax, [msg+MSG.wParam]
mov esp, ebp
pop ebp
ret 16


Here the same setup, the stack frame, the definitions.... by the way, I have named SavedEBP for show what is the place of the saved EBP, the ret Address also have a definition, you can delete the definitions (because make look a little ugly the code :)...., by the way, here I dont use the definition and use directly ebp-n for access the arguments....


WndProc:
push ebp
mov ebp, esp
%define SavedEBP ebp
%define SavedRetAddress ebp+4
%define hWnd ebp+8
%define uMsg ebp+12
%define wParam ebp+16
%define lParam ebp+20
mov eax, [uMsg]
cmp eax, WM_DESTROY
je .WM_DESTROY
apicall DefWindowProcA, [ebp+8], [ebp+12], [ebp+16], [ebp+20]
mov esp, ebp
pop ebp
ret 16
.WM_DESTROY:
apicall PostQuitMessage, 0
xor eax, eax
mov esp, ebp
pop ebp
ret 16



Copy each part of code if you whant to assemble it.
Posted on 2004-12-23 21:06:10 by rea
Thanks you very much for your help. :D That's exactly what I was looking for..
Posted on 2004-12-24 09:17:54 by dev_zero
I was missing to say taht you can read this one: http://194.65.3.199/win32asm/tutorial/stack_apj.txt

Also, you can find some more info here: http://rs1.szif.hu/~tomcat/win32/


If you whant more about http://www.win32asmcommunity.net/board/viewtopic.php?t=11425
Posted on 2004-12-24 10:45:36 by rea