EN NL TR
Assembler & Win64
This small article is about how to write in assembler for Windows 64-bit, it isn't ment for the IA64 but the new 64-bit version of x86 environment (also called x86-64 or x64 or AMD64/EM64T (EM64T is sometimes misreferred to as EMT64) or AA-64). I'm also assuming you know about Win32 assembler programming, if not : check out Iczelion's Win32 Asembly Homepage (even though the site isn't updated anymore, Iczelion still has my respect for his work).
When I starting writing this (july 2004), the SDK for developing programs for the x64 wasn't made public yet, it was only available in the DDK for Windows Server 2003 (which can be ordered online). You can now (may 2005) freely download the required files with the Windows Server 2003 SP1 Platform SDK. You don't have to install the whole Platform SDK to assemble and link the examples listed below. You only need to install the follow options :
This page has quite some success so
I decided to write some more about Win64-programming. If you want,
check out this article about RIP
In order to create a simple Win64 assembler program you will need to following files from the DDK :
Make sure you are using kernel32.lib and user32.lib from the amd64 subdirectory!
The x86-64 expands some existing registers : rax, rcx, rdx, ebx, rsp, rbp, rsi, rdi, rip (these are 64-bit versions of eax, ecx, edx, ebx, esp, ebp, esi, edi, eip respectively). And it defines 8 new registers : r8, r9, r10, r11, r12, r13, r14, r15, the 32-versions of these registers are : r8d, r9d, r10d, .... And the be complete, r8w, r9w, ... are the 16-bit variants (the low word) for the new registers and r8b, r9b, ... are the 8-bit variants (the low byte).
If you have existing Win32 assembler programs, you may have been thinking it will be easy to convert them, but my first experience with Win64 assembler has told me otherwise :-(. In Win32, all the parameters are passed via the stack, however in Win64 they are passed via the registers.
Note that the
used registers (for parameter passing) are based on the size of the
parameter. For 32-bit parameters these are: ecx, edx, r8d,
... and for 64-bit parameters there ase : rcx, rdx, r8,
r9, r10, ...
The following code will display a small message box :
This is an old version that no longer assembles correctly with the newer ml64's (!) :
NOTE: for you to see the difference, I've added the 32-bit version :
In order the compile the 64-version (see above), you need to invoke ml64 like this :
ml64 XXX.asm /link /subsystem:windows /defaultlib:kernel32.lib /defaultlib:user32.lib /entry:main
(assuming kernel32.lib and user32.lib reside in the same directory as ml64.exe)
(where XXX is the name of your assembly file)
NOTE: I've added the option /entry:main because newer versions of
link.exe require this!
Note that the Macro Assembler (x64) doesn't accept the .386 and the .model keywords. They are probably some others too but I've got no clue which ones :), I'm too bored to test them.
Also "mov rax, offset X" isn't accepted, use
"lea rax, X" instead!
You can also use YASM to create a Win64 executables starting with version 0.5.0. Older versions won't work.
In order to assemble try this : yasm-0.5.0-win.exe -f win64 XXX.asm
You can now use the resulting XXX.obj file with the linker (link.exe in the AMD64-subdirectory of your SDK) : link XXX.obj /subsystem:windows /defaultlib:kernel32.lib /defaultlib:user32.lib /entry:main
Notice the "global main" in the source code, and know that the entry-point is case-sensitive!
Also, the code for ML64 and YASM are incompatible!
ML64 doesn't accept the BITS 64 keyword and YASM
doesn't accept the .CODE, .STACK and .DATA keywords!
Starting with version 1.61.3 you could also use flat assembler to build 64-bit object files, but you still need Microsoft's Linker from the Platform SDK to create the exe file. And starting with version 1.64 you can use flat assembler to directly build 64-bit executable files!
This shows how to use FASM to build a PE64 executable directly :
And if you want to use a linker to build the executable, use this :
In order to assemble try this : fasm XXX.asm
Code writting for ML64 and flat assembler are incompatible with each other!
note that you need to write lea reg, [variable] whereas ML64
accepts lea reg, variable.
Now you know the basics of how to write for Win64 (x64), go out and write some code! Let's forget about the 32-bit world...