Programovanie v assembleri vo Windows x64 (x86-64): Rozdiel medzi revíziami

Smazaný obsah Přidaný obsah
Fabcde (diskusia | príspevky)
Bez shrnutí editace
URL -> wikilinky
Riadok 1:
Toto sú poznámky k niekoľkým jednoduchým programom napísaných v jazyku [[w:Jazyk_symbolických_inštrukcií|symbolických adries]] (assembly language) určených pre [https[w://cs.wikipedia.org/wiki/Po%C4%8D%C3%ADta%C4%8Dov%C3%A1_platforma:Počítačová platforma|platformu]] '''[[w:X86-64|x86-64]]''' – '''Windows x64'''.
 
== Stručný prehľad ==
=== Syntax a kompilácia ===
Väčšina programov v tomto dokumente je uvedená v dvoch verziách - prvá pre [[w:Prekladač|prekladač]] (kompilátor) [[w:Netwide_Assembler|Netwide Assembler]] (NASM), druhá pre [https[w://cs.wikipedia.org/wiki/GNU_Assembler:GNU Assembler|GNU Assembler]] (GAS). NASM používa syntax Intelu, dominujúcu v prostredí MS-DOS a Windows, GNU Asembler používa syntax AT&T, prevládajúcu v Unixovom svete. Asi najmätúcejším rozdielom týchto dvoch syntaxí je prehodené poradie argumentov niektorých inštrukcií.<ref>Ram Narayan (2007-10-17). [https://www.ibm.com/developerworks/library/l-gas-nasm/index.html "Linux assemblers: A comparison of GAS and NASM"]
</ref> Napríklad inštrukcia "vlož hodnotu nula do registra AX" sa v NASM zapisuje <code>MOV AX, 0</code>, v GAS <code>MOV $0, %AX</code>. (Intelovská syntax pripomína priraďovací príkaz vyšších programovacích jazykov <code>AX = 0</code>, syntax AT&T skôr niečo ako <code>0 -> AX</code>.)
 
Skompilovaním zdrojového súboru príslušným kompilátorom (nasm resp. as) vznikne [https[w://cs.wikipedia.org/wiki/Objektov%C3%BD_k%C3%B3d:Objektový kód|objektový súbor]], ktorý je následne pomocou [https[w://cs.wikipedia.org/wiki/:Linker |linkeru]] golink, resp. ld zlinkovaný do výsledného spustiteľného súboru. Kompilátor as (GNU Assembler) a linker ld sú súčasťou [[w:GNU_Compiler_Collection|gcc]]. Kvôli jednoduchšiemu rozlíšeniu majú tu uvedené [[w:Zdrojový_kód|zdrojové súbory]] programov určených pre NASM príponu .asm, objektové .obj, a pre GNU Assembler príponu .s, resp .o.
 
=== Volanie WinAPI ===
Programy bežiace v [https[w://cs.wikipedia.org/wiki/Re%C3%A1ln%C3%BD_re%C5%BEim:Reálný režim|Reálnom móde]] (operačný systém MS-DOS) prípadne aj v móde (režime) [https[w://cs.wikipedia.org/wiki/Virtual_8086_mode:Virtual 8086 mode|Virtual 8086]] (operačný systém Windows) mohli využívať služby operačného systému MS-DOS prostredníctvom [[wikipedia:MS-DOS_API|MS-DOS API]]. Tieto sa volali pomocou [https[w://cs.wikipedia.org/wiki/P%C5%99eru%C5%A1en%C3%AD:Přerušení#Softwarov.C3.A9_p.C5.99eru.C5.A1en.C3.ADSoftwarové přerušení|softvérového prerušenia]] inštrukciou INT, napríklad <code>INT 21h</code><ref>[http://www.cs.cmu.edu/~ralf/files.html Ralf Brown's Interrupt List]</ref>. Nakoľko 64-bitové verzie OS Windows režim Virtual 8086 nepodporujú, služby operačného systému je už možné zabezpečiť výlučne volaním funkcií [https[w://cs.wikipedia.org/wiki/Windows_API:Windows API|Windows API]] (WinAPI).
 
Funkcii (podprogramu) je zvyčajne potrebné nejakým spôsobom odovzdať argumenty a opačným smerom zase výsledok. V zásade nie sú žiadne obmedzenia týkajúce sa spôsobu odovzdávania údajov medzi volajúcim a volaným podprogramom. Je možné zvoliť akýkoľvek fungujúci spôsob, či už pomocou registrov, pamäti, zásobníka, atď, len treba o každej volanej funkcii (podprograme) vedieť, kde očakáva argumenty a kam ukladá výsledok. Kvôli veľkému množstvu funkcií, ktoré sú k dispozícii (bežný prípad knižníc), bolo nutné zaviesť nejaké spoločné pravidlá - [https[w://cs.wikipedia.org/wiki/Volac%C3%AD_konvence:Volací konvence|volacie konvencie]] (calling convention).
 
Toto sú niektoré z najčastejšie používaných [[wikipedia:X86_calling_conventions|volacích konvencií v prostredí MS Windows]]:
Riadok 190:
 
=== Zásobník ===
[https[w://cs.wikipedia.org/wiki/Z%C3%A1sobn%C3%ADk_%28datov%C3%A1_struktura%29:Zásobník (datová struktura)|Zásobník]] (stack) je pamäťová štruktúra typu LIFO. Hardvérový zásobník je realizovaný priamo v operačnej pamäti počítača. V ďalšom texte zásobníkom budeme rozumieť vždy hardvérový zásobník, nie nejakú jeho softvérovú implementáciu.
 
Zásobník je možné používať ľubovoľne podľa potreby. Bežne sa používa na ukladanie lokálnych premenných, alebo dočasných, pomocných hodnôt. Často sa používa aj na odovzdávanie argumentov podprogramu. Inštrukcia CALL na vrchol zásobníka ukladá návratovú adresu z podprogramu.
Riadok 233:
</syntaxhighlight>Nepotrebné miesto na vrchole zásobníka uvoľní:<syntaxhighlight lang="nasm">
ADD RSP, n
</syntaxhighlight>''Poznámka:'' Rozhranie X86-64 ABI použité v [https[w://cs.wikipedia.org/wiki/UNIX_System_V:UNIX System V|System V]] umožňuje používať aj [[wikipedia:Red_zone_(computing)|Red zone]] - oblasť 128 bajtov tesne nad vrcholom zásobníka.
 
=== Podprogram ===
Volanie funkcie (podprogramu) sa v jazyku symbolických adries realizuje inštrukciou CALL. Inštrukcia najskôr vloží na vrchol zásobníka hodnotu registra RIP ([https[w://cs.wikipedia.org/wiki/%C4%8C%C3%ADta%C4%8D_instrukc%C3%AD:Čítač instrukcí|Instruction Pointer]], niekedy nazývaný aj PC - Program Counter), v ktorom sa už nachádza adresa ďalšej inštrukcie. Následne zmenou hodnoty registra RIP sa zrealizuje skok na požadovanú adresu. Podprogram končí inštrukciou RET, ktorá odoberie z vrcholu zásobníka návratovú adresu (pôvodnú hodnotu registra RIP) a vloží ju späť do registra RIP. Program potom pokračuje tam, kde bol prerušený podprogramom, čiže inštrukciou bezprostredne nasledujúcou za inštrukciou CALL.
 
=== Volacia konvencia Microsoft x64 ===
Riadok 346:
</syntaxhighlight>inštrukciou<syntaxhighlight lang="nasm" line="1" start="47">
xor ecx, ecx ; 1. param _In_ UINT uExitCode UINT je 32 bit aj v 64 bitovom prostredi
</syntaxhighlight>Je to pokus o optimalizáciu kódu, kedže inštrukcia xor ecx,ecx tiež vynuluje obsah registra ECX, ale po preložení zaberá menej bajtov. Optimalizácia kódu je však dnes kvôli prúdovému spracovaniu inštrukcií ([https[w://cs.wikipedia.org/wiki/:Pipelining |pipelining]]), hypertredingu, cache pamäti, atď mimoriadne zložitá a vyžaduje hlboké znalosti. Spravidla dobrý kompilátor/optimalizátor jazyka C dokáže vytvoriť rýchlejší kód než hoci aj kratší ale neoptimalizovaný kód v jazyku symbolických adries.<ref>https://www.zive.cz/clanky/vyznejte-se-v-procesoru--velky-prehled-technologii/historie-procesoru-cache-a-skalarni-procesory/sc-3-a-147124-ch-66129/default.aspx#articleStart</ref><ref>http://frdsa.fri.uniza.sk/~janosik/Kniha/Prudove_sprac.html</ref><ref>https://forum.root.cz/index.php?topic=2388.0</ref>
 
'''Výpis 4''' HelloWorld.s (Verzia pre GAS):<syntaxhighlight lang="nasm" line="1">