|
Afgedankte code |
EN NL TR |
|
Assembler & Win64 Dit korte artikel gaat over hoe men een programma moet schrijven voor Windows 64-bit, het is niet bedoeld voor de IA64 maar voor de nieuwe 64-bit-versie van de x86 (deze wordt ook x86-64, x64 of AMD64/EM64T/AA-64 genoemd (EM64T wordt soms verkeerd geschreven als EMT64)). Ik ga er vanuit dat je overweg kan met Win32-assembler, indien niet : ga dan even kijken op Iczelion's Win32 Assembly Homepage (ook al wordt de site niet meer aangepast tegenwoordig, Iczelion krijgt toch mijn respect voor zijn werk). Toen ik dit schreef (juli 2004), was de SDK voor het schrijven van x64-programma's nog niet publiek gemaakt, hij was enkel verkrijgbaar via de DDK voor Windows Server 2003 (welke online gekocht kan worden). De benodigde bestanden kunnen nu (mei 2005) vrijlijk gedownload worden met de Windows Server 2003 SP1 Platform SDK. U hoeft niet de ganse Platform SDK te installeren om de onderstaande voorbeelden te kunnen assembleren. Enkel de volgende opties zijn vereist :
Om Win64-programma's te debuggen kan je Microsoft's gratis downloadbare debugger gebruiken (de 64-bit-versie kan je hier vinden). Deze pagina bleek vrij populair te
zijn dus heb ik besloten nog wat meer te schrijven over x64-programmen.
Als het u interesseert, lees dan dit artikel over RIP-relatieve adressering.
Om een simpel Win64-assembler-programma te maken heb je de volgende bestanden uit de DDK nodig :
Let er op dat u kernel32.lib en user32.lib gebruikt uit de amd64-subfolder! De x86-64 heeft bestaande registers uitgebreid : rax, rcx, rdx, ebx, rsp, rbp, rsi, rdi, rip (dit zijn 64-bit-versies van respectievelijk eax, ecx, edx, ebx, esp, ebp, esi, edi, eip). En komt 8 met nieuwe registers : r8, r9, r10, r11, r12, r13, r14, r15, de 32-versies van zijn deze registers zijn : r8d, r9d, r10d, .... En om compleet te zijn, r8w, r9w, ... zijn de 16-bit-varianten (de lage word/low word) van deze nieuwe registers en r8b, r9b, ... zijn de 8-bit-varianten (de lage byte/low byte). Indien je bestaande Win32-assembler-programma's hebt, dan heb je misschien zitten denken dat het makkelijk ging zijn om ze om te zetten naar Win64, maar niets is minder waar. Mijn eerste ervaringen met Win64-assembler leerden me de waarheid :-(. In Win32 worden alle parameters via de stack doorgegeven, maar in Win64 worden ze doorgegeven via de registers. Noteer dat de gebruikte registers (voor de
parameter-doorgave) afhankelijk zijn van de grootte van de door-te-geven
parameter. Voor de 32-bit-parameters zijn dit: ecx, edx, r8d,
r9d, r10d,
... en voor de 64-bit-parameters zijn dit : rcx, rdx, r8,
r9, r10, ... De onderstaande code toont een "message box" :
Dit is een oudere versie welke niet meer geassembleerd kan worden met de nieuwe versies van ml64 :
NOTA: zodat je het verschil kunt zien, heb ik hier de 32-bit versie geplaatst :
Om de 64 bit-versie (zie bovenaan) te assembleren, start je ml64 zo : ml64 XXX.asm /link /subsystem:windows /defaultlib:kernel32.lib /defaultlib:user32.lib /entry:main (er van uitgaande dat kernel32.lib en user32.lib zich in dezelfde folder bevinden als ml64.exe) en (waar XXX de naam is van het assemblerbestand)
NOTA: Ik heb de optie /entry:main toegevoegd omdat de nieuwere
versies van link.exe dit vereisen! Noteer dat de Macro Assembler (x64) het .386 en het .model sleutelwoord niet accepteerd. Er zijn er waarschijnlijk nog maar ik zou niet weten de welke :), en ik heb er geen zin om dit te onderzoeken.
Ook: "mov rax, offset X" is niet
ondersteund, gebruik in plaats hiervan:
"lea rax, X"! Vanaf versie 0.5.0 kan je ook YASM gebruiken om een Win64-programma te maken. Met de oudere versies werkt het niet!
Om te assembleren doe je dit : yasm-0.5.0-win.exe -f win64 XXX.asm Om te linken gebruik je de linker (link.exe) uit de SDK (uit de AMD64-subdirectory) : link XXX.obj /subsystem:windows /defaultlib:kernel32.lib /defaultlib:user32.lib /entry:main Noteer "global main" en weet dat het ingangspunt (entry-point) hoofdlettergevoelig is!
Noteer ook dit: de code voor ML64 en YASM is niet direct uitwisselbaar!
ML64 accepteerd het BITS 64-sleutelwoord niet en YASM
accepteerd de .CODE, .STACK en .DATA-sleutelwoorden niet! Beginnend met versie 1.61.3 kan flat assembler ook gebruikt worden om 64-bit-objectbestanden te maken, de Microsoft Linker uit de Platform SDK is echter nog steeds vereist om het uiteindelijke exe-bestand maken. Vanaf versie 1.64 heb je geen Microsoft Linker meer nodig! Onderstaand voorbeeld toont aan hoe je een PE64-exe-bestand rechtstreeks moet aanmaken :
En als je een linker wenst te gebruiken dan doe je het zo :
Om te assembleren doe je dit : fasm XXX.asm
Code geschreven voor ML64 en flat assembler zijn niet compatibel met
elkaar! En noteer ook nog dat je lea reg, [variable]
moet schrijven terwijl je voor ML64 lea reg, variable moet
schrijven. En nu dat je weet hoe je aan Win64 (x64) moet beginnen, ga en programmeer! Laten we de 32-bit wereld vergeten...
|