TITLE: WIN32 ASSEMBLER TUTORIAL CHAPTER 0.5
Diese Seite gibts auch in Deutsch
WIN32 ASSEMBLER TUTORIAL CHAPTER 0.5
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:
- Code, Data and Stack are in the same memory area and start at the same base address (yippieh).
- The limit for Code+Data+Stack is 4GB, in theory. At the moment the maximum space is either 2GB (W95/98/ME) or 3GB (some NT/2000), but that's enough, isn't it?
- We will NEVER need segment registers any more - they point to the same area in the memory anyway. Always mind this rule: DS is equal to ES, but CS is not equal to DS but a so-called alias (blah, blah, blah).
- You can't modify the code using CS but you can do it using DS, ES or SS (okay, that's not that important either).
- If you try to access an area in the memory which you haven't reserved for your program, Windows will kick your program out with a cool error message (nice for to detecting bugs in your program).
- The stack can be as large as it or you want (well, until you get a memory overflow). If you know something about descriptors, you can figure out easily how that's realized. (And the stack always works - so forget the rest.)
What makes Win32 coding that damned c00l?
- Video memory, Code, Data, File-I/O, Sound output: Everything is located in the same segment - never care about 64k limits any more.
- All registers can be used as 32bit pointers to the memory.
- Standardized functions instead of special routines for special hardware.
2. What you need:
- Assembler+Linker. For this tute: NASM+ALINK, TASM+TLINK or MASM+LINK. MASM and TASM are almost identical in their usage, NASM has its own syntax. I´ve attached extra source files for NASM.
- As soon as you code Windows proggies on your own: A Win32 API manual called Platform SDK. It's a necessary encyclopedia for coding in Windows.
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:
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:
ExitProcess equ _ExitProcess@4
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:
segment .data USE32 (NASM)
The Data itself is yet missing:
ErrorCode dd 0
Same goes for the Code segment:
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:
And for NASM:
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:
Finished. Now you only have to implement the program.
4. Compiling and Linking
The following configuration is essential:
- Case-sensitive symbols
- Windowing compatible (-aa or SUBSYSTEM:WINDOWS)
- Win32-EXE file
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
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.
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,
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
you can write
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,...