flat assembler
Message board for the users of flat assembler.

Index > Windows > Learning Win32 programming

Goto page 1, 2, 3  Next
Author
Thread Post new topic Reply to topic
Inagawa



Joined: 24 Mar 2012
Posts: 153
Inagawa 20 Apr 2012, 13:18
Hello, I thought I'd make a new topic, since I finally want to tackle Win32 programming. I have downloaded the FASM version of Iczelion's Win32 tutorials, but it's obvious I can't learn just from that. Is there a book on Win that you guys would recommend? For beginners. Thanks Wink

Is Programming Windows, 5th Edition a good choice?


Last edited by Inagawa on 21 Apr 2012, 08:44; edited 1 time in total
Post 20 Apr 2012, 13:18
View user's profile Send private message Reply with quote
AsmGuru62



Joined: 28 Jan 2004
Posts: 1619
Location: Toronto, Canada
AsmGuru62 20 Apr 2012, 13:49
I suggest take the 'English PDF' from here:
http://www.winprog.org/tutorial/

It starts from the very beginning and code in the book is C code.
But it can easily translated into ASM.
Post 20 Apr 2012, 13:49
View user's profile Send private message Send e-mail Reply with quote
dancho



Joined: 06 Mar 2011
Posts: 74
dancho 20 Apr 2012, 16:40
like I said in other thread Smile ,
for the start psdk and Iczelion is enough,
go to the lesson 3,it is very simple,read it,understand it ,look for info in sdk,
( Windowing section is first I can think of ) ,and ask questions...
gl
Post 20 Apr 2012, 16:40
View user's profile Send private message Reply with quote
mindcooler



Joined: 01 Dec 2009
Posts: 423
Location: Västerås, Sweden
mindcooler 20 Apr 2012, 19:06
Here's my take on a GUI hello world:

http://files.sys5.se/hellogui.zip

Search msdn (with Google, it's faster) for the api calls made.

_________________
This is a block of text that can be added to posts you make.
Post 20 Apr 2012, 19:06
View user's profile Send private message Visit poster's website MSN Messenger ICQ Number Reply with quote
Inagawa



Joined: 24 Mar 2012
Posts: 153
Inagawa 21 Apr 2012, 08:26
Thanks a lot for all the suggestions and the code sample. But mindcooler, what is the virtual for? I've checked the documentation, but to be honest, I'm none the wiser.
Code:
;@ WindowProc:
        virtual at esp+8
                .wmsg  rd 1
        end virtual
    


What do you gain by this? If I understand correctly, .wmsg becomes a synonym for ESP+8. Why not just do a .wmsg equ ESP+8?

At least it appears to work the same as if I use a .wmsg equ esp+8.


Also, one thing that has been going through my mind. There is no WinMain, anywhere. Does windows require WinMain, does FASM create it for me?
Post 21 Apr 2012, 08:26
View user's profile Send private message Reply with quote
AsmGuru62



Joined: 28 Jan 2004
Posts: 1619
Location: Toronto, Canada
AsmGuru62 21 Apr 2012, 11:32
WinMain is provided for you by a C/C++ compiler.
FASM has no such ability.
You can get parameters for WinMain by using APIs.
Code:
;
; WinMain (hInstance, hPrevInstance, pszCmdLine, iCmdShow)
;
invoke GetModuleHandle, 0
mov [hInstance], eax
;
; hPrevInstance is never needed in Win32 (it was needed in Win16)
;
invoke GetCommandLineA
mov [pszCmdLine], eax
;
; iCmdShow is needed in some rare cases. It is a parameter
; usually passed to ShowWindow to display main application
; window for the first time. Just pass SW_NORMAL for now.
; If you really need this parameter -- use GetStartupInfo API to get it.
;
    

So, basically, you have no need for WinMain.

P.S. I use 'virtual' for structures. There is a MASM-born macro struct/ends,
which allows to use structures, but I am not using it because the type of the element in a structure
can be only one of types defined by FASM, like DD,DW,DB, etc.
'virtual' however allows to use a type alias, which makes code much more readable.
For example:
Code:
HWND equ dd
HFONT equ dd
PRECT equ dd
CHARS equ rb

...

virtual at 0
OBJECT1:
     .pRect1 PRECT ?
     .hFont  HFONT ?
     .path   CHARS 256
   .size = $
end virtual
;
; at this point the OBJECT1 can be used as a structure.
; you can get it size by using OBJECT1.size and access its members by using
; the proper expression with a member name:
;
mov esi, ... ; <-- load address of a structure into a register
mov eax, [esi + OBJECT1.hFont]   ; Load the font handle
;
; or use it in API calls without loading it into a register
;
invoke GetClientRect, [hWnd], [esi + OBJECT1.pRect]
;
    
Post 21 Apr 2012, 11:32
View user's profile Send private message Send e-mail Reply with quote
l_inc



Joined: 23 Oct 2009
Posts: 881
l_inc 21 Apr 2012, 12:49
AsmGuru62
Quote:
the type of the element in a structure
can be only one of types defined by FASM, like DD,DW,DB, etc.

Not true. Also other structures and unions can be a field type. And the aliasing can be done in a very similar way:
Code:
struc HWND [args] { common . dd args }
struc HFONT [args] { common . dd args }
struc PRECT [args] { common . dd args }
struc CHARS [args] { common . rb args }

struct OBJECT
        pRect1 PRECT ? 
        hFont  HFONT ? 
        path   CHARS 256 
ends    

Furthermore struct allows you to define OBJECT variables (not just the labels like OBJECT.pRect1), make them be field types of other structures, defines sizeof for every field and for the whole structure. Thus it's a very bad suggestion to avoid using struct.
Post 21 Apr 2012, 12:49
View user's profile Send private message Reply with quote
Inagawa



Joined: 24 Mar 2012
Posts: 153
Inagawa 21 Apr 2012, 13:18
Shouldn't the size be ".size = $ - OBJECT1" or something like that?

Anyway, using structures it bad or good? And what exactly do you mean by object variables? How are object variables different from labels, they both point to a chunk of memory, no?
Post 21 Apr 2012, 13:18
View user's profile Send private message Reply with quote
l_inc



Joined: 23 Oct 2009
Posts: 881
l_inc 21 Apr 2012, 13:54
Inagawa
Quote:
Shouldn't the size be ".size = $ - OBJECT1"

It should. And it is. Because OBJECT1 equals to zero: virtual at 0 means, that the virtual addressing space will start addressing from zero.
Quote:
Anyway, using structures it bad or good?

As for me, using struct (note the difference between struc and struct) is very handy.
Quote:
And what exactly do you mean by object variables?

Defining a variable of the structure type OBJECT is the following:
Code:
;a structure with defined fields:
obj1 OBJECT 0x401234,2,'Hello, world!'
;a structure with undefined fields
obj2 OBJECT    

This allocates memory for obj1 and obj2 and defines labels to this memory obj1.pRect1, obj2.pRect1 and so on.
Both is impossible with the approach of AsmGuru62.
Quote:
How are object variables different from labels, they both point to a chunk of memory, no?

No. Variables do not point. They are those chunks of memory. A label itself does not have to point to a valid location. So the definition:
Code:
struct OBJECT 
        pRect1 PRECT ?  
        hFont  HFONT ?  
        path   CHARS 256  
ends    

defines a number of labels zero-based labels OBJECT.pRect1, OBJECT.hFont, OBJECT.path. Neither of them points to a valid location. But those a very useful, when working with register-based structures, like mov eax, [esi + OBJECT1.hFont] from the AsmGuru62's example. The above definition also defines numeric constants: sizeof.OBJECT, sizeof.pRect1, sizeof.hFont and sizeof.path. And as I said OBJECT can also become a field type of some other structure (also impossible with the AsmGuru62's approach).
Post 21 Apr 2012, 13:54
View user's profile Send private message Reply with quote
mindcooler



Joined: 01 Dec 2009
Posts: 423
Location: Västerås, Sweden
mindcooler 21 Apr 2012, 13:58
Inagawa wrote:
What do you gain by this? If I understand correctly, .wmsg becomes a synonym for ESP+8. Why not just do a .wmsg equ ESP+8?


As I'm only using .wmsg in this example you can do it with a somple equ, but if you have several consecutive aliases, then virtual makes it easier by auto-increasing the offset;

I only found an example with two parameters, but anyway Smile

Code:
WindowProc:
 virtual at esp+8
 .wmsg  rd 1
 .wp    rd 1
 end virtual    


Edit:

Found some more real-life examples:

Code:
virtual at ebp
     w1     rq 1
     w2     rq 1
     w3     rq 1
     w4     rq 1
end virtual

virtual at esi
     x1     rq 1
     x2     rq 1
     x3     rq 1
     x4     rq 1
end virtual

lea     edi,[w3]
fld     [x3]    


Quote:
00401503 |. 8D7D 10 LEA EDI,[EBP+10]
00401506 |. DD46 10 FLD [QWORD DS:ESI+10]

_________________
This is a block of text that can be added to posts you make.


Last edited by mindcooler on 21 Apr 2012, 14:11; edited 1 time in total
Post 21 Apr 2012, 13:58
View user's profile Send private message Visit poster's website MSN Messenger ICQ Number Reply with quote
l_inc



Joined: 23 Oct 2009
Posts: 881
l_inc 21 Apr 2012, 14:08
Inagawa
Quote:
Code:
;@ WindowProc: 
        virtual at esp+8 
                .wmsg  rd 1 
        end virtual    
What do you gain by this? If I understand correctly, .wmsg becomes a synonym for ESP+8. Why not just do a .wmsg equ ESP+8?

This code is in fact equivalent to
Code:
label .wmsg dword at esp+8    

So there is a label definition. The label is register-based and bound to the dword size. In contrast .wmsg equ ESP+8 does not define any labels (and btw. is resolved at preprocessing stage). So there're a lot of differences, but the most important are probably that .wmsg becomes visible and interfering with the following code (after the end of the procedure, i.e. after a new global label is defined), and e.g. push [.wmsg] would only compile in the first case, because then the label has a known size (dword).
Post 21 Apr 2012, 14:08
View user's profile Send private message Reply with quote
Inagawa



Joined: 24 Mar 2012
Posts: 153
Inagawa 21 Apr 2012, 14:11
Thank you guys. I'll try to wrap my head around all of this new info and come back to you on this.
Post 21 Apr 2012, 14:11
View user's profile Send private message Reply with quote
dancho



Joined: 06 Mar 2011
Posts: 74
dancho 21 Apr 2012, 19:12
@Inagawa
maybe would be easier to understand if you read this first :

http://flatassembler.net/docs.php?article=win32#1.1
Post 21 Apr 2012, 19:12
View user's profile Send private message Reply with quote
AsmGuru62



Joined: 28 Jan 2004
Posts: 1619
Location: Toronto, Canada
AsmGuru62 22 Apr 2012, 14:36
@l_inc: very nice! Thanks! I did not know that it can be done.
I generate some of my code with IDE. So, if I need to declare an object within the other object IDE does this:
Code:
BYTES equ rb

...

virtual at 0
OBJECT2:
  .chunk1 BYTES OBJECT1.size
  .chunk2 BYTES OBJECT1.size
  .chunk3 BYTES OBJECT1.size
end virtual
    

and then to access it I point register to the field:
Code:
    ;
   ; EBX points to OBJECT2
     ;
   lea     esi, [ebx + OBJECT2.chunk3]
 mov     eax, [esi + OBJECT1.hFont]
    

or sometimes I use a combined offset, like so:
Code:
 mov     eax, dword [ebx + OBJECT1.hFont + OBJECT2.chunk3]
    

Of course, it is a little inconvenient.
Proper structs provide easier coding, but I have been coding like that for years. It will be hard to re-learn a new way.

The new IDE I am writing will have easier way of coding, like:
Code:
  mov     eax, this.chunk3.hFont
      call    this.OnCreate (loc.vectCells, loc.uiNumCells, glb.hHeap, L"HELLO")
    

And the code generator runs through this script doing stuff, like
- putting UNICODE text "HELLO" into data section,
- calling virtual methods,
- passing local and global variables,
- etc.
Post 22 Apr 2012, 14:36
View user's profile Send private message Send e-mail Reply with quote
bzdashek



Joined: 15 Feb 2012
Posts: 147
Location: Tolstokvashino, Russia
bzdashek 22 Apr 2012, 19:02
AsmGuru62 wrote:

The new IDE I am writing will have easier way of coding, like:
Code:
 mov     eax, this.chunk3.hFont
      call    this.OnCreate (loc.vectCells, loc.uiNumCells, glb.hHeap, L"HELLO")
    

And the code generator runs through this script doing stuff, like
- putting UNICODE text "HELLO" into data section,
- calling virtual methods,
- passing local and global variables,
- etc.

Wow, this.going to be a great thing.

Btw, while searching for the ways to trap WM_KEYDOWN event, I ran into some of your replies on "programmers heaven", dated 19 nov 2003 ~ 23 nov 2003. You were suggesting to a person subclass some procedure, and he was grateful.
That might bring some old memories: http://www.programmersheaven.com/mb/windows/225781/226489/re-wm_keydown-never--more/?S=B10000

Smile

Sorry for the off-topic.
Post 22 Apr 2012, 19:02
View user's profile Send private message Reply with quote
AsmGuru62



Joined: 28 Jan 2004
Posts: 1619
Location: Toronto, Canada
AsmGuru62 22 Apr 2012, 21:26
Smile Nice.

programmersheaven got really disorganized a couple of years ago.
My password got reset for some reason -- I sent a request to change password,
but the site was not working properly and new password (sent to me) was also not working.
I tried few things, like waiting for some time and logging in again -- no luck.
It looked like new password(s) were expiring in, like, 5 sec.

So, my help on PH ended at that point.

New IDE will be indeed interesting, but it will be good for new projects.
If you have some old code -- IDE will not be of much use, because it
will have a different approach to code. Also, I am writing a form designer, so
dialogs (or forms) can be created quickly in visual manner.
Post 22 Apr 2012, 21:26
View user's profile Send private message Send e-mail Reply with quote
Inagawa



Joined: 24 Mar 2012
Posts: 153
Inagawa 23 Apr 2012, 19:40
Hi there, I get a weird error. Guru, you told me that labels are unique to their procedure, then why am I getting an error? What have I overlooked?

Code:
proc !IsLetter uses edx, Character

  ;
  ; Making all the characters lowercase makes evaulation
  ; easier
  ;
  stdcall      !ToLowercase, [Character]

  mov          ecx, 26
  mov          edx, 97
SearchCharacters:
  cmp          eax, edx
  je           CharacterFound
  inc          edx
  loop         SearchCharacters

  ;
  ; If the [Character] is not a letter, return 0
  ;
  mov          eax, 0
  ret

CharacterFound:
  mov          eax, 1

  ret
endp    


Is !IsNumber, okay? It's telling me its labels SearchCharacters and CharacterFound are both already defined.

Code:
proc !IsNumber uses edx, Character

  mov          ecx, 10
  mov          edx, 48
SearchCharacters:
  cmp          [Character], edx
  je           CharacterFound
  inc          edx
  loop         SearchCharacters

  ;
  ; If the [Character] is not a number, return 0
  ;
  mov          eax, 0
  ret

CharacterFound:
  mov          eax, 1

  ret
endp    


The first error I get is that CharacterFound is already defined here in !IsAlphanumeric. When I exclude this procedure from the program, there aren't any conflicts. I fail to see what is wrong here..
Code:
proc !IsAlphanumeric uses edx, Character

  stdcall      !IsLetter, [Character]
  mov          edx, eax
  stdcall      !IsNumber, [Character]
  or           edx, eax
  cmp          edx, 1
  je           CharacterFound
  mov          eax, 0
  ret

CharacterFound:
  mov          eax, 1

  ret
endp    


Thanks for any help, it's probably something completely silly that I've overlooked.
Post 23 Apr 2012, 19:40
View user's profile Send private message Reply with quote
AsmGuru62



Joined: 28 Jan 2004
Posts: 1619
Location: Toronto, Canada
AsmGuru62 23 Apr 2012, 21:20
to get labels differentiated in diff. procs -- you need to prefix these labels with a dot (.).
Just replace "CharacterFound:" with ".CharacterFound:" and
of course if you jump or call this label - use the dot too, like so:

jmp .CharacterFound
Post 23 Apr 2012, 21:20
View user's profile Send private message Send e-mail Reply with quote
Inagawa



Joined: 24 Mar 2012
Posts: 153
Inagawa 23 Apr 2012, 21:28
Thanks, that solved it. I thought labels are unique no matter the dot - guess I was wrong.
Post 23 Apr 2012, 21:28
View user's profile Send private message Reply with quote
AsmGuru62



Joined: 28 Jan 2004
Posts: 1619
Location: Toronto, Canada
AsmGuru62 23 Apr 2012, 22:01
You can even jump into the middle of a procedure if needed, like so:
Code:
proc1:
       ...
 jmp     proc2.LABEL1
        ...
 ret

proc2:
       ...
.LABEL1:
 ...
 ret
    

If both procedures have the same ending code, you can do that to make the code smaller, but watch out for local variables - they must be the same size for both procedures. If you remember the FORTRAN language -- it has the same ability with ENTRY statement.
Post 23 Apr 2012, 22:01
View user's profile Send private message Send e-mail Reply with quote
Display posts from previous:
Post new topic Reply to topic

Jump to:  
Goto page 1, 2, 3  Next

< Last Thread | Next Thread >
Forum Rules:
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum
You cannot attach files in this forum
You can download files in this forum


Copyright © 1999-2024, Tomasz Grysztar. Also on GitHub, YouTube.

Website powered by rwasa.