Toby Opferman http://www.opferman.net programming@opferman.net Win32 Assembly Introduction (TASM v5.0) "Functions, Defines, and Variable Defintions" This tutor is for those who know Win32 API programming in C, C++ or simular language, know the concepts of Event-Driven programming, have a working knowledge of the basic Win32 API, and know assembly who want to learn Win32 assembly. If you do not know Event Driven programming, read the tutor I wrote on GUI - Event Driven programming OR get a book on beginning windows programming. First off, I want to explain that programming Assembly for Win32 can be as easy as programming C. So, we will start with the API and how to use the definitions. Before you can start programming Win32 Assembly, you need to define structures and functions. When using C, all this is done for you, you just #include <windows.h> and done! Well, in Assembly, unless you search the web or you have an assembler other than tasm that may have .INC's, you have to define all your prodecures & structures. Luckily, tasm does have a WIN32.INC which does define a lot of data types and a few functions (But not many). Under TASM\EXAMPLES\WAP32 you will find WIN32.INC. You can use this and add on to it. That is a lot better than starting off with nothing. We will start with how to define functions. This is quite simple, just: extrn BeginPaint:PROC That's it! Remeber, Win32 IS case sensitive in some areas, and this is one of them. CALL BeginPaint ; A Call To Begin Paint Simple. We will get to parameters in a bit. But, there is one catch. UNICODE. UNICODE is something I do not really know a lot about. It has something to do with the way Character strings are stored. There are two types: ANSI WIDE CHARACTER. UniCode defines the wide character form. If you have the C header files, you can do a GREP (This comes with TASM) on UNICODE and you will see how functions are redefined. I assume ANSI for all my programs. Wide character for (I think) means each character is 2 bytes instead of one. But I am not sure, if someone knows UNICODE and wants to explain it totally please email me. So, when you define any function that has String Input, you MUST define it with either an A on the end or a W on the end. (I always do A cause I use ANSI) extrn TextOutA:PROC That is how TextOut would be defined. Now, you would have to: CALL TextOutA ; Call to Text Out Ansi Of course,to avoid the annoying A/W thing you can: TextOut equ <TextOutA> Then Just CALL TextOut ; Call To Text Out If your program wanted to change to Wide character then, you would only have to change the extrn and equ instead of the whole program so this is a good idea and good practice. Next on the list is defining the Data types/structures. Well, that's simple. It would be a good idea to have a API reference with the Functions & Data type defines structures so you can define them in your program. Or, if you have a windows C compiler like Watcom or Visual C you may grep -w <yourword> directory\*.h to find structure defines so you may define them in your WIN32.INC. Defining Structures: MSGSTRUCT struc msHWND UINT ? msMESSAGE UINT ? msWPARAM UINT ? msLPARAM ULONG ? msTIME ULONG ? msPT ULONG 2 dup(?) MSGSTRUCT ends Defining Types: HDC equ <dd> Now, I will show you how to pass parameters. There is a function of TASM 5.0 to pass like high level, with all your parms in the call: CALL FUNC, Parms This is a bit TOO high level for me, might as well start using C, and Asm in Win32 is High Level Enough!! But, if you like that way, you can use that way. Here is the Manual way: (P.S. I would do a L equ <LONG> so you can use on the Pushes to make sure that dword parms are pushed as dwords if you push a VALUE or Value Defintion like equ's. Pushing offsets, memory locations or registers is fine since the compiler will know the size.) PUSH L 0 PUSH L 0 PUSH L 0 PUSH OFFSET Msg CALL GetMessage ; Call Get Message Now, you see that the parameters are pushed on backwards. in C: GetMessage(&Msg, 0, 0, 0); // 0 or NULL Anyway, you see that the parameters are pushed on backwards. (TIP: If you like the C 'NULL' idea NULL equ <0> ; C Sytle Null's ) All return values are in EAX. So, as in our example, you know that the GetMessage returns a ZERO when your application quits. MessageLoop: PUSH L 0 PUSH L 0 PUSH L 0 PUSH OFFSET Msg CALL GetMessage ; Call To GetMessage TEST EAX, EAX ; Quit Loop? JZ SHORT EndProgram PUSH OFFSET Msg CALL TranslateMessage ; Translate Message PUSH OFFSET Msg CALL DispatchMessage ; Dispatch Message JMP SHORT MessageLoop EndProgram: PUSH [Msg.wParam] CALL ExitProcess ; End Program As you see, the Return value of GetMessage is in EAX. That is the jist of getting started. All you need to know from this tutor is: 1. How to define variables & API Function Definitions including ANSI/WIDE character modes. 2. How to successfully pass parameters, call and get a return value from an API function If you have accomplished these, you are ready to move on to my Win32 Intermediate programming tutor which tells how to create a Win32 Program.