--->Diese Seite gibts auch in Deutsch.
TITLE: WIN32 ASSEMBLER TUTORIAL CHAPTER 0.5
AUTHOR: T$

WIN32 ASSEMBLER TUTORIAL CHAPTER 0.5
-=(T$)=-

All you need for this tute is an Assembler and Win95/98/ME/NT/2000/XP. Of course you should also know a little about ASM programming. The sources are included (zip). Since I don't know what else I should write in this introduction, let's start with the content:

1. Win32 Coding

If you have coded in DPMI, you won't have any problems to port your code to Win32. Win32 programs run in the 32bit Protected Mode with a FLAT memory model. That means: What makes Win32 coding that damned c00l?

2. What you need:

3.1 Let's start

First, let's tell our Assembler that we want to write 32bit code.
For TASM or MASM, use the following:

                .386
                .model flat
If you use NASM, you have to specify this with the segments (see below).

The Windows functions use a lot of constant values which are described in the SDK. They are defined in windows.inc or win32n.inc, so let's put these files into the code:

         %include "win32n.inc"  (NASM)
         include windows.inc    (TASM/MASM)
The Windows functions are in DLLs. They are accessed to using NEAR calls (not interrupts) and are hence EXTERN. MASM uses different names for these functions than TASM and NASM. The following code for TASM/MASM solves the problem:
        IFDEF masm
         ExitProcess equ _ExitProcess@4
        ENDIF
This must be done for every function called in MASM.

Now let's insert the function:
        extrn ExitProcess : near
NASM needs a special invitation for this, which has to include the name of the DLL:
        IMPORT ExitProcess kernel32.dll

Now it's time to implement the data. Both Code and Data fit into a segment. Still it's better to define these segments separately. Then you only have to specify the relevant segment in order to mix Code and Data in the Code. The linker will split them again:

                .data                (TASM/MASM)
                segment .data USE32  (NASM)
The Data itself is yet missing:
                ErrorCode dd 0
Same goes for the Code segment:
                .code
or
                segment .code USE32  (NASM)

Here the program starts. The entry point does not necessarily have to be called main or WinMan, in ASM you can also call it _YerMothersFace (great insider movie in my area, btw) if you want. But _beginning is okay, too:

               _beginning:
And for NASM:
              ..start
Wow, now we are right in a working Win32 program! Before you wet your pants with excitement, I'd better stop. But, wait a moment... YES, the function to quit the program must be called, too.

3.2 Win32 Functions

All API functions with a constant number of parameters (I know only one exception) are called using the stdcall convention. That is, all parameters are PUSHed onto the stack from right to left and then the function is called. The function clears the stack and returns its value in the EAX register.

In general, the parameters are passed as DWORDs.

The code looks like that:
                push ErrorCode
                call ExitProcess
Finished. Now you only have to implement the program.

4. Compiling and Linking

The following configuration is essential: Look up the exact command line parameters in the zip.

5. Hey, the program doesn't do anything!

That's right. That's why I extended the finished file with a standard Windows dialogue. You could evaluate the return value here and, e. g. , call the function again when the wrong button has been pressed...

6. Other basic topics

6.1 Resources

Resources is data which is linked in the program file. All kinds of data are allowed. This feature is mainly used for icons, menus, and multiple language support (Windows loads the right language automatically!)...

In order to create resources, you need a resource script (*.RC).. It describes the resources that are to be linked in your .exe file. You can create resource scripts using a text editor or a special resource editor. It's compiled together with the data to a *.res or *.obj file, which then gets passed to the linker. A resource compiler and an icon are included in the bonus archive, too.

6.2 Functions

To use Win32 functions, you have to include the required *.lib files in the program. While TASM stores all functions in import32.lib, MASM has a separate LIB for every DLL. That means that if you use MASM, you have to check what DLL contains the function you need.

BTW, Strings are always passed as pointers. They are either terminated by zero or their length is passed as a separate parameter. The registers EBX, ESI, EDI, and EBP remain unchanged, the DF flag has to be cleared before calling a function.

In Windows NT, all string functions are available twice: once for the ANSI and once for the UNICODE charset. Apart from a few exceptions, Win95 only contains the ANSI functions. Therefore the SDK function CreateFile actually exists twice: once as CreateFileA for ANSI and once as CreateFileW for UNICODE. In Assembler, you have to specify the exact type.

6.3. Functions in DLLs for which you have no LIBs

No problem at all: If you have no LIB, you create one yourself.

For TASM, you first use IMPDEF in order to retrieve a *.def file from the DLL and then use the *.def file with IMPLIB to create the *.lib.

MASM users: Use DUMPBIN /exports with the DLL, remove everything in the *.def except the lines with the functions, decorate the functions like the following,

   Function_name  @Number_of_parameters_in_bytes
add
   LIBRARY  dllname
   EXPORTS
to the head of the file and then have LIB /def do the rest about the *.def.

Attention: LIB.EXE automatically adds an underscore _ to all functions!

If you use NASM, take a glance at the DOCs of the linker.

6.4 How do these LIBs work?

LIBs contain information what DLLs and what functions are used. Windows loads these and inserts their addresses in the places which are specified in our code by the LIBs. If we call a function, the CALL first goes to the LIB, then there is a JMP with the right address. MASM (and partly also NASM) users can also access the targets of the JMPs using labels, so instead of
     call ExitProcess@4
you can write
     call [__imp__ExitProcess@4]
and in this way the execution of the JMP instruction is removed.

7. Argh, I'm confused... I'd thought this would be simple.

Well, it's all a matter of getting accustomed. Your first programming attempts weren't that simple either, were they?

But don't worry: The sourcecode in asmtut0e.zip should be easy to understand, and using the SDK you can experiment a little with it without great problems.

This time was a lot of theory. The most important thing is for now how to get the compiler/linker to work and get an overview.

In the next chapter the actual stuff starts: windows, message/input handling,...
Mail the Author: webmeister@deinmeister.de

Homepage Programming Win32Asm Downloads Software Hardware Cartoons Sitemap