flat assembler
Message board for the users of flat assembler.
Index
> Windows > Win32 programming without includes Goto page 1, 2 Next |
Author |
|
revolution 29 Aug 2008, 13:18
pal: Have a look at struc in the fasm manual. Like this:
Code: struc abc { .x dd ? .y dd ? } |
|||
29 Aug 2008, 13:18 |
|
pal 29 Aug 2008, 14:15
Yeah I see. I would like to have done it without macro's to be honest but I dunno how thats possible. As I am creating a window and if I have no includes should I too replace a proc endp with a macro then?
Out of curiosity; there is obviously a way to do this without proc and without macro's, but I cant figure it out seeing as in my window callback prodecure parameters are passed to it. Am I correct in thinking that if I specify a label as my callback procedure then the parameters passed to be will be located at (on the stack): hWnd -> [EBP+8] uMsg -> [EBP+C] wParam -> [EBP+10] lParam -> [EBP+14] If so, and as they are on the stack does that mean I could use them by doing the following: Code: mov ax,ss:[ebp+8] Or something as such to move say ebp+8 (hWnd) to a register or whatever? |
|||
29 Aug 2008, 14:15 |
|
revolution 29 Aug 2008, 14:22
Parameters in STDCALL (used in most Windows APIs) are pushed reverse order onto the stack. So you can access directly with something like "mov eax,[esp+8]". But of course you can set ebp to the stack beginning at entry and use the code you posted above "mov eax,[ebp+8]". Although using the macro proc makes all the finicky offset and label value calculations for you. I recommend you use the macro simply to make your job easier.
|
|||
29 Aug 2008, 14:22 |
|
LocoDelAssembly 29 Aug 2008, 14:28
mov eax, [ebp+8] is enough. Here another convinient way
Code: winproc: virtual at ebp+8 .hWnd dd ? .uMsg dd ? .wParam dd ? .lParam dd ? end virtual push ebp mov ebp, esp mov eax, [.hWnd] ; EAX because HWND is dword sized and no SS because DS segment covers the entire 4 GB space like all the other segment registers do (except for FS and GS). leave ret 4*4 I'll move the posts to "Win32 programming without includes" later. |
|||
29 Aug 2008, 14:28 |
|
pal 29 Aug 2008, 15:54
OK, I think I'm coming to understanding this more. hWnd, uMsg, wParam and lParam are all dwords hence they are all at a +4 value of ebp (dword = 4 bytes). So I tried to make a really basic dialog using something like this (the code is below), but the thing fucked up badly. It was trying to include d0.dll for some reason then h0.dll (when I added a message box for some error handling) and I have no idea where it got the idea to do that from.
Code: format PE GUI 4.0 entry start section '.data' data readable writeable cClass db 'WINDOWFASM',0 hWnd dd ? uMsg dd ? wParam dd ? lParam dd ? NULL equ 0 section '.code' code readable executable start: ; Get handle push NULL call [GetModuleHandle] ; Create a window push 0 push WndProc push 0 ; HWND_DESKTOP push 37 push eax call [DialogParamBox] ret WndProc: mov eax,[esp+08h] mov [hWnd],eax mov eax,[esp+0Ch] mov [uMsg],eax mov eax,[esp+10h] mov [wParam],eax mov eax,[esp+14h] mov [lParam],eax ; Got the params now lets see the message cmp [uMsg],10 ; WM_CLOSE je wmClose wmDefault: push [lParam] push [wParam] push [uMsg] push [hWnd] call [DefWindowProc] jmp wmEnd wmClose: push 1 push [hWnd] call [EndDialog] wmEnd: ret section '.idata' import data readable writeable dd 0,0,0,RVA kernel_table,RVA kernel_name dd 0,0,0,RVA user_name,RVA user_table dd 0,0,0,0,0 kernel_table: GetModuleHandle dd RVA _GetModuleHandle user_table: DefWindowProc dd RVA _DefWindowProc EndDialog dd RVA _EndDialog DialogParamBox dd RVA _DialogParamBox kernel_name db 'KERNEL32.DLL',0 user_name db 'USER32.DLL',0 _GetModuleHandle dw 0 db 'GetModuleHandleA',0 _DefWindowProc dw 0 db 'DefWindowProcA',0 _EndDialog dw 0 db 'EndDialog',0 _DialogParamBox dw 0 db 'DialogParamBoxA',0 section '.reloc' fixups data readable discardable I decided to use DialogBoxParamA instead of CreateWindowExA so that I didn't have to use a macro to define the WNDCLASS(EX) structure. I know hWnd should really be called hWndDlg but meh. Also I wasn't able to move the item from the stack directly to my memory locations; I had to move it to eax first then from eax to the memory location. Any help apprechiated. |
|||
29 Aug 2008, 15:54 |
|
revolution 29 Aug 2008, 16:00
You must use [esp+4] for the first parameter if you don't push a value onto the stack. The [ebp+8] is used when the original ebp is pushed onto the stack.
|
|||
29 Aug 2008, 16:00 |
|
pal 29 Aug 2008, 18:14
OK; I think I understand. I read some articles on the net, I don't really understand why this is happening too much but I apprechiate it. From what I've gathered esp is the stack pointer to the top address of the stack, but I don't understand the difference between that and ebp. When you mentioned about the origional ebp being pushed onto the stack, is that to preserve the value or what?
Also any idea why the program is crashing upon trying to load the DLL which it shouldn't be. I'm assuming for some reason trying to load kernel32.dll or user32.dll its getting a malformed string somehow which it is trying to load. Does this website have an IRC channel by the way? |
|||
29 Aug 2008, 18:14 |
|
revolution 29 Aug 2008, 22:44
pal wrote: Also any idea why the program is crashing upon trying to load the DLL which it shouldn't be. I'm assuming for some reason trying to load kernel32.dll or user32.dll its getting a malformed string somehow which it is trying to load. |
|||
29 Aug 2008, 22:44 |
|
Frank 30 Aug 2008, 12:55
pal wrote:
Mere eye-balling suggests that one of the above lines must be wrong, note the different order of xxx_table and xxx_name. pal wrote:
DialogBoxParamA? |
|||
30 Aug 2008, 12:55 |
|
asmcoder 30 Aug 2008, 14:48
[content deleted]
Last edited by asmcoder on 14 Aug 2009, 14:56; edited 1 time in total |
|||
30 Aug 2008, 14:48 |
|
pal 31 Aug 2008, 11:45
Cheers for the replies. Cant believe that I was spelling DialogBoxParam DialogParamBox Also about putting user_table and user_name the wrong way around.
asmcoder: So your saying I should be using: Code: section '.idata' import readable And by "db 0,0,'export',0 " I assume your talking about replacing lines such as: Code: _EndDialog dw 0 db 'EndDialog',0 With that; or am I mistaken. I changed the code and have tried a few things now but I'm getting the same results; I've tried: Code: mov eax,dword [esp+04h] (with and without dword) pop eax mov eax,dword [ebp+08h] (with and without dword and after pushing ebp) But none of them work. If I do use mov instead of pop does that mean I have to realign esp so that the values are no longer on the stack, as I am not actually pop'ing them but just copying them aren't I? |
|||
31 Aug 2008, 11:45 |
|
revolution 31 Aug 2008, 16:56
See the code that LocoDelAssembly posted above. If you are getting confused with esp then start by using ebp instead the way LocoDelAssembly suggests.
|
|||
31 Aug 2008, 16:56 |
|
Alphonso 31 Aug 2008, 20:47
Not sure why your doing it like this, seems a hard way to do it, but if that's what you want then maybe
Code: format PE GUI 4.0 entry start section '.data' data readable writeable cClass db 'WINDOWFASM',0 hWnd dd ? uMsg dd ? wParam dd ? lParam dd ? NULL equ 0 section '.code' code readable executable start: ; Get handle push NULL call [GetModuleHandle] ; Create a window push 0 push WndProc push 0 ; HWND_DESKTOP push 37 ;--> ID=37 but where is the dialog resource? push eax call [DialogParamBox] ret WndProc: mov eax,[esp+04h] mov [hWnd],eax mov eax,[esp+08h] mov [uMsg],eax mov eax,[esp+0ch] mov [wParam],eax mov eax,[esp+10h] mov [lParam],eax ; Got the params now lets see the message cmp [uMsg],10h ; WM_CLOSE --> 10h not 10 je wmClose wmDefault: push [lParam] push [wParam] push [uMsg] push [hWnd] call [DefWindowProc] jmp wmEnd wmClose: push 1 push [hWnd] call [EndDialog] wmEnd: mov eax,0 ;--> all done ret section '.idata' import data readable writeable dd 0,0,0,RVA kernel_name ,RVA kernel_table dd 0,0,0,RVA user_name ,RVA user_table dd 0,0,0,0,0 kernel_table: GetModuleHandle dd RVA _GetModuleHandle dd 0 ;End of table user_table: DefWindowProc dd RVA _DefWindowProc EndDialog dd RVA _EndDialog DialogParamBox dd RVA _DialogParamBox dd 0 ;End of table kernel_name db 'KERNEL32.DLL',0 user_name db 'USER32.DLL',0 _GetModuleHandle dw 0 db 'GetModuleHandleA',0 _DefWindowProc dw 0 db 'DefWindowProcA',0 _EndDialog dw 0 db 'EndDialog',0 _DialogParamBox dw 0 db 'DialogBoxParamA',0 ;not ...ParamBox section '.reloc' fixups data readable discardable I'm not so good at this stuff but hope it helps. |
|||
31 Aug 2008, 20:47 |
|
pal 31 Aug 2008, 20:50
Nevermind, I have it now with the esp+4 etc. Cheers for all the help. What was wrong was that when I looked at what Frank said about the two lines, one being wrong and I made them both wrong! I've fixed it now anyway. And yeah Alphonso thats what I'm doing/have now, cheers!
|
|||
31 Aug 2008, 20:50 |
|
pal 03 Sep 2008, 23:31
Just a quick follow up question/problem. I have a code which I reckon should be working, so does another coder I showed it too, but the CreateWindowEx() function returns null, and GetLastError() function returns the error 1407 (if I remember correctly), which equates to "Cannot find window class". I have no idea why this is as I am getting a valid atom back from the RegisterClass call. I have tried this with both WNDCLASS and WNDCLASSEX structures, but both failed. The code is:
Code: format PE GUI entry start section '.data' data readable writeable ; Our callback procedure variables hWnd dd 0 uMsg dd 0 wParam dd 0 lParam dd 0 ; Other variables winWnd dd ? cClassName db 'FASMDIALOG',0 cTitle db 'Window Title',0 cError db 260 dup (0) ; WNDCLASS wCls: wCls.style dd 0 wCls.lpfnWndProc dd WndProc wCls.cbClsExtra dd 0 wCls.cbWndExtra dd 0 wCls.hInstance dd 0 wCls.hIcon dd 0 wCls.hCursor dd 0 wCls.hbrBackground dd 0 wCls.lpszMenuName dd 0 wCls.lpszClassName dd cClassName ; MSG wMsg: wMsg.hWnd dd 0 wMsg.message dd 0 wMsg.wParam dd 0 wMsg.lParam dd 0 wMsg.time dd 0 wMsg.pt.x dd 0 wMsg.pt.y dd 0 section '.code' code readable writeable start: push 0 call [GetModuleHandle] mov [wCls.hInstance],eax ; Load an icon push 32512 push 0 call [LoadIcon] mov [wCls.hIcon],eax ; Load a cursor push 32512 push 0 call [LoadCursor] mov [wCls.hCursor],eax ; Register class push wCls call [RegisterClass] cmp eax,0 je errGetError ; Create a window push 0 push wCls.hInstance push 0 push 0 push 200 ; nHeight push 300 ; nWidth push 16 ; y push 16 ; x push 0x16CF0000 ; dwStyle (WS_VISIBLE+WS_DLGFRAME+WS_SYSMENU) push cTitle push wCls.lpszClassName push 0 call [CreateWindowEx] cmp eax,0 je errGetError mov [winWnd],eax ; Show the window push 5 push eax call [ShowWindow] ; Our message loop messageLoop: push 0 push 0 push 0 push wMsg call [GetMessage] or eax,eax je endCode ; Translate message push wCls call [TranslateMessage] ; Dispatch message push wCls call [DispatchMessage] jmp messageLoop WndProc: push ebp pusha mov ebp,esp mov eax,[ebp+0x8] mov [hWnd],eax mov eax,[ebp+0xC] mov [uMsg],eax mov eax,[ebp+0x10] mov [wParam],eax mov eax,[ebp+0x14] mov [lParam],eax xor eax,eax cmp [uMsg],0x2 ; WM_DESTROY je wmDestroy wmDefault: push [lParam] push [wParam] push [uMsg] push [hWnd] call [DefWindowProc] jmp wmEnd wmDestroy: push 0 call [PostQuitMessage] xor eax,eax wmEnd: popa ret errGetError: call [GetLastError] push 0 push 260 push cError push 0 push eax push 0 push 0x1000 ; FORMAT_MESSAGE_FROM_SYSTEM call [FormatMessage] push 0 push 0 push cError push 0 call [MessageBox] endCode: push 0 call [ExitProcess] section '.idata' import readable dd 0,0,0,RVA user_name ,RVA user_table dd 0,0,0,RVA kernel_name ,RVA kernel_table dd 0,0,0,0,0 kernel_table: GetModuleHandle dd RVA _GetModuleHandle FormatMessage dd RVA _FormatMessage GetLastError dd RVA _GetLastError ExitProcess dd RVA _ExitProcess dd 0 user_table: MessageBox dd RVA _MessageBox CreateWindowEx dd RVA _CreateWindowEx RegisterClass dd RVA _RegisterClass DispatchMessage dd RVA _DispatchMessage TranslateMessage dd RVA _TranslateMessage DefWindowProc dd RVA _DefWindowProc GetMessage dd RVA _GetMessage LoadIcon dd RVA _LoadIcon LoadCursor dd RVA _LoadCursor PostQuitMessage dd RVA _PostQuitMessage ShowWindow dd RVA _ShowWindow dd 0 user_name db 'USER32.DLL',0 kernel_name db 'KERNEL32.DLL',0 _GetModuleHandle dw 0 db 'GetModuleHandleA',0 _FormatMessage dw 0 db 'FormatMessageA',0 _GetLastError dw 0 db 'GetLastError',0 _ExitProcess dw 0 db 'ExitProcess',0 _MessageBox dw 0 db 'MessageBoxA',0 _CreateWindowEx dw 0 db 'CreateWindowExA',0 _RegisterClass dw 0 db 'RegisterClassA',0 _DispatchMessage dw 0 db 'DispatchMessageA',0 _TranslateMessage dw 0 db 'TranslateMessage',0 _DefWindowProc dw 0 db 'DefWindowProcA',0 _GetMessage dw 0 db 'GetMessageA',0 _LoadIcon dw 0 db 'LoadIconA',0 _LoadCursor dw 0 db 'LoadCursorA',0 _PostQuitMessage dw 0 db 'PostQuitMessage',0 _ShowWindow dw 0 db 'ShowWindow',0 Any help is apprechiated, Unknown. |
|||
03 Sep 2008, 23:31 |
|
LocoDelAssembly 03 Sep 2008, 23:56
Seems that other coder haven't paid you too much attention
push wCls.hInstance > push [wCls.hInstance] push wCls.lpszClassName > push [wCls.lpszClassName ] pusha > ; pusha popa > ; popa insert "leave" before ret Code: ; Translate message push wCls call [TranslateMessage] ; Dispatch message push wCls call [DispatchMessage] To: Code: ; Translate message push wMsg call [TranslateMessage] ; Dispatch message push wMsg call [DispatchMessage] Some fixing will still be needed but now it doesn't crash nor hung neither. |
|||
03 Sep 2008, 23:56 |
|
pal 04 Sep 2008, 09:28
Cheers! I cant believe again my error was passing the wrong parameter because of my ignorance Two things: as for putting [] around the two members of the wCls structure, I looked at one of karl's (I think) examples, and he didn't have brackets around them, but it still worked. I used brackets at first but it wasn't working so I changed it so it was like his... If i use the leave command, don't I need an enter at the beginning of the callback procedure?
Got it working now, I had to move the pusha command to after the mov ebp,esp command. When I had 0 for WNDCLASS.hbrBackground the window was seethrough (except for the frame), is this normal because there is no specified colour? Cheers, Unknown. |
|||
04 Sep 2008, 09:28 |
|
LocoDelAssembly 04 Sep 2008, 14:24
Quote:
Yes, because there is no background brush. And in fact you don't see through, the window "memorizes" what was in the portion of screen just before the background became visible. Quote:
But still your "xor eax, eax" won't make your procedure return zero because popa restores eax too. stdcall procedures (like winproc and, with some exceptions, all the APIs), only need to preserve EBX, ESI, EDI and EBP and ESP must be restored to ESP-number_of_args*4 (in some cases some arguments can be longer than 4, a multiple of 4). So there is another bug that I haven't seen before, ret must be "ret 16" if you don't apply this change you could have random crashes. About ENTER, check the manual to see what it does, you'll find out that you already used it without noting it. |
|||
04 Sep 2008, 14:24 |
|
pal 07 Sep 2008, 12:29
Ahh cool. Just a few questions to clear up:
1. I only need to preserve ebp, esp, esi, edi, and ebx during my function, and pop them at the end. In the case of esp I need to subtract 16 (4 params * 4 dwords?). Do I have to do this for all of my functions, as in change esp? 2. As for the ret 16, will I need to put this in any other functions like my one above, obviously if there are only two params then 8 or whatever? |
|||
07 Sep 2008, 12:29 |
|
Goto page 1, 2 Next < Last Thread | Next Thread > |
Forum Rules:
|
Copyright © 1999-2024, Tomasz Grysztar. Also on GitHub, YouTube.
Website powered by rwasa.