Programovanie v assembleri vo Windows x64 (x86-64): Rozdiel medzi revíziami
Smazaný obsah Přidaný obsah
Značka: Vrátenie |
d formulácie |
||
Riadok 94:
G:\>objdump -fhD HelloWorld.obj
</syntaxhighlight>Direktíva <code>global main</code> deklaruje návestie main ako globálne a linker ho môže použiť ako štartovaciu adresu programu.
Direktíva <code>extern GetStdHandle</code> deklaruje symbol GetStdHandle (WinAPI funkcia) ako externý, čiže nachádzajúci sa v niektorom z ďalších pripojených súborov, v tomto prípade v dynamicky linkovanej knižnici kernel32.dll. Napriek tej 32 v názve, vo Windows x64 je to 64-bitová knižnica, o čom sa môžeme presvedčiť ďalším užitočným programom 7-Zip:<syntaxhighlight>
G:\>"C:\Program Files\7-Zip\7z.exe" l c:\windows\system32\kernel32.dll
</syntaxhighlight>
Direktíva <code>section .text use64</code> uvádza nasledujúci segment ako programový.
Na adrese message je uložený text pozdravu. Keďže sa nachádza v sekcii kódu, obsah tejto pamäťovej oblasti program môže čítať, ale pokus o jej modifikáciu vedie ku okamžitému ukončeniu programu. (Dá sa o tom jednoducho presvedčiť preusnutím premennej lpNumberOfBytesWritten do sekcii kódu. Program skončí chybou ERRORLEVEL=-1073741819 "Access violation.")
Konštanta MESSAGE_LEN obsahuje počet bajtov (dĺžku textu), ktorý chceme vypísať. Konštanta, na rozdiel od premennej, nie je uložená na nejakej konkrétnej adrese, ale v čase kompilácie bude každý odkaz na ňu, napríklad <code>mov r8d, dword MESSAGE_LEN</code> nahradený jej skutočnou hodnotou <code>mov r8d, 15</code> (podobne ako <code>#define MESSAGE_LEN 15</code> v jazyku C).
Riadok 243:
=== Volacia konvencia Microsoft x64 ===
64-bitové verzie funkcií WindowsAPI, rovnako ako aj funkcie knižníc GCC, MS Visual Studio (do 2013), Delphi, používajú volaciu konvenciu Microsoft x64<ref name=":0" />.
Prvé štyri argumenty sú uložené v registroch (64-bitová architektúra x86-64 má oproti 32-bitovej architektúre x86 k dispozícii viac registrov). V prípade celočíselných hodnôt (vrátane ukazovateľov), v RCX, RDX, R8 a R9 (v tomto poradí), v prípade argumentov s pohyblivou desatinnou čiarkou v XMM0, XMM1, XMM2, XMM3. Prvý argument je teda uložený buď v registri RCX alebo v XMM0, druhý v RDX alebo v XMM1, tretí v R8 alebo v XMM2, štvrtý v R9 alebo v XMM3. Parametre menšie než 64 bitov ignorujú vyššie bity, netreba ich nulovať. Napríklad prvý parameter typu integer (aj v x86-64 je to 32 bitové celé číslo) stačí uložiť do ECX.
Riadok 304:
extern WriteFile
extern ExitProcess
Řádek 315 ⟶ 311:
main:
sub rsp,
; rax = GetStdHandle(-11)
Řádek 326 ⟶ 322:
; BOOL bErrorFlag = WINAPI WriteFile (_In_ HANDLE hFile, _In_ LPCVOID lpBuffer, _In_ DWORD nNumberOfBytesToWrite, _Out_opt_ LPDWORD lpNumberOfBytesWritten, _Inout_opt_ LPOVERLAPPED lpOverlapped)
; WriteConsole(handle, &msg[0], 13, &written, 0)
mov rcx, rax ; 1. param _In_ HANDLE hFile (8B)
mov rdx, qword message ; 2. param _In_ LPCVOID lpBuffer (8B)
mov r8d, dword MESSAGE_LEN ; 3. param _In_ DWORD nNumberOfBytesToWrite (4B)
mov r9,
mov qword [rsp+20h], 0 ; 5. param _Inout_opt_ LPOVERLAPPED lpOverlapped (8B)
call WriteFile
Řádek 338 ⟶ 334:
call ExitProcess
add rsp,
</syntaxhighlight>Rozdiel v porovnaní s prvou verziou spočíva v rezervovaní miesta v zásobníku tak, aby sa sem
sub rsp,
</syntaxhighlight>Piaty argument potom samozrejme nie je možné vložiť na požadovanú pozíciu inštrukciou PUSH, ale:<syntaxhighlight lang="nasm" line="1" start="
mov qword [rsp+20h], 0 ; 5. param _Inout_opt_ LPOVERLAPPED lpOverlapped (8B)
</syntaxhighlight>Zásobník je pripravený aj pre funkciu ExitProcess, stačí ju zavolať a až potom uvoľniť rezervované miesto:<syntaxhighlight lang="nasm" line="1" start="
add rsp,
</syntaxhighlight>Poslednou zmenou je nahradenie inštrukcie<syntaxhighlight lang="nasm" line="1" start="
mov ecx, 0 ; 1. param _In_ UINT uExitCode UINT je 32 bit aj v 64 bitovom prostredi
</syntaxhighlight>inštrukciou<syntaxhighlight lang="nasm" line="1" start="
xor ecx, ecx ; 1. param _In_ UINT uExitCode UINT je 32 bit aj v 64 bitovom prostredi
</syntaxhighlight>
Řádek 365 ⟶ 361:
.global main
.section .text
Řádek 374 ⟶ 367:
main:
sub $
mov $-11, %ecx
call GetStdHandle
mov %rax, %rcx
mov $message, %rdx
mov $MESSAGE_LEN, %r8d
mov
movq $0, 0x20(%rsp)
call WriteFile
xor %ecx, %ecx
call ExitProcess
add $
</syntaxhighlight>Za povšimnutie stojí zápis nepriamej adresácie (používanej napríklad pri indexovaní poľa). Kým v NASM to bolo: <code>mov qword [rsp + 20h], 0</code>, v GAS je "index" uvedený pred zátvorkou: <code>movq $0, 0x20(%rsp)</code>
Řádek 414 ⟶ 407:
=== Hello, World! v.3 ===
Posledná verzia programu Hello, World vypíše text pomocou funkcie
'''Výpis 3a''' HelloWorld.asm:<syntaxhighlight lang="nasm" line="1">
Řádek 447 ⟶ 440:
ret
</syntaxhighlight>
== Rozširujeme ==
|