Lekce 4 - Assembler - Vytvoření NASM projektu, registry a přerušení
V minulé lekci, Assembler - Převod čísla na řetězec a naopak, jsme převáděli mezi číslem a řetězcem na obě strany.
Dnes se podíváme na to, jaký zvolit software pro vývoj v ASM, založíme svůj první ASM projekt a řekneme si co jsou to registry a přerušení.
Software pro programování v ASM
Pro vývoj v ASM budeme jako pro vývoj v každém jazyce potřebovat editor kódu a překladač. Sice nepotřebujeme překladač ve významu překladače programovacího jazyka do binárky, ale stále musíme náš ASM kód nějak převést na spustitelnou binárku. Víme, že píšeme instrukce slovy, čísla v desítkové soustavě a tomu by počítač ještě stále nerozuměl.
Editor
Vlastně je na každém z nás, jaký editor kódu zvolíme. Soubory totiž
budeme vždy ukládat ve formě textu, ale namísto přípony .txt
použijeme příponu .asm
. Pro začátek můžeme použít
obyčejný textový editor (Poznámkový blok), ale ten nemá zvýrazňování
syntaxe a nelze z něj klávesovou zkratkou spustit kompilátor. Proto je
lepší zvolit nějaký vývojářský editor.
Já osobně dávám přednost českému PSPadu. Další editor vhodný pro programátory je Notepad++ s pluginem NppExec. Existují i vývojová prostředí (IDE) zaměřená na assembler. Například Easy Code má podporu pro několik různých kompilátorů a navíc obsahuje nástroje pro vytváření uživatelských rozhraní ve Windows:
Pokud chceme své programy také ladit, pak je lepší volbou Microsoft Visual Studio, které má sice mizerný editor, ale dobrý debugger.
Kompilátor
Ve výsledku nechceme soubor ve formě textu, ale spustitelný binární soubor. Existuje mnoho kompilátorů (neboli překladačů), ale bohužel nejsou navzájem kompatibilní. Proto dříve než vůbec začneme programovat, je důležité si dobře rozmyslet, který kompilátor budeme používat. Pokud bychom později zjistili, že nám zvolený kompilátor nevyhovuje, bylo by nesmírně pracné přepisovat všechen svůj kód. Většina kompilátorů (kromě GAS a HLA) používají syntaxi Intel. To znamená, že instrukce jsou až na pár detailů stejné. Velké rozdíly jsou ale ve způsobu zápisu funkcí, proměnných a maker.
Nejznámější kompilátory ASM jsou:
- NASM - Netwide Assembler - populární multiplatformní kompilátor ASM. Není příliš vhodný pro začátečníky, protože nekontroluje typy proměnných a má komplikovanou syntaxi pro deklaraci funkcí a lokálních proměnných.
- FASM - Flat Assembler - velmi dobrý multiplatformní kompilátor, který je o něco novější a pokročilejší než NASM. Má velmi propracovaná makra. Zajímavé je, že FASM je celý naprogramován v ASM, kompiluje tedy sám sebe.
- MASM - Microsoft Macro Assembler - populární Assembler, ale jak asi tušíte, je vázán na Windows / MS-DOS a nemá otevřenou licenci. Je prakticky použitelný pouze pro 32-bitové aplikace. Posledních několik let ho Microsoft téměř nevyvíjí a nepodporuje.
- JWasm - je zcela kompatibilní s MASM, ale na rozdíl od něj má open-source licenci, podporuje i Linux a lze v něm vytvářet 64-bitové aplikace. Vývoj skončil v roce 2014.
- UASM - nástupce JWasm. Má mnoho pokročilých funkcí, například instrukce AVX512, volací konvence VECTORCALL a SYSTEMV, textové řetězce v UTF-8, příkaz .switch. Dokonce umožňuje objektově orientované programování a volání funkcí jako v jazyce C++.
- Asmc - další nástupce JWasm. Obsahuje aktuální hlavičkové soubory pro Windows (včetně DirectX 11 a OpenGL) a funguje v něm ladění ve Visual Studiu 2019.
- POASM - Pelles Macro Assembler - je součástí vývojového prostředí PellesC pro programovací jazyk C. Je částečně kompatibilní s MASM, ale není tak dobrý jako JWasm. Jedinou výhodou je kvalitní debugger, který je na rozdíl od Microsoft Visual Studia mnohem rychlejší, spotřebuje desetkrát méně paměti a má zvýrazňování syntaxe.
- GoASM - je součástí Go Tools, které obsahují
kompilátor ASM, linker, kompilátor resources a také jednoduchý debugger.
GoASM nekontroluje typy proměnných a má mírně odlišnou syntaxi. Názvy
typů se musejí zapisovat jedním písmenem. V instrukcích skoků jsou znaky
>
a<
pro skok dopředu nebo dozadu. - Sol_Asm - Solar Assembler - Na tomto assembleru je zajímavé, že jeho autor v něm napsal svůj vlastní operační systém Solar_OS. Bohužel nechce zveřejnit jeho zdrojové kódy. Sol_Asm neumí SSE instrukce.
- GAS - GNU Assembler - výchozí překladač pro GCC
(kompiler céčka a tedy celého Linuxu). Používá starší standard AT&T,
ne Intel. Syntaxe je zcela odlišná od všech ostatních kompilátorů. Před
registry se musí psát
%
, instrukce mají operandy v opačném pořadí, místo hranatých závorek jsou kulaté závorky. - HLA - High Level Assembler - vypadá podobně jako PASCAL a je určen především na výuku. Obsahuje velmi podrobný manuál (několik stovek stránek v PDF) a spoustu příkladů. Syntaxe je ale příliš odlišná od všech ostatních kompilátorů. Na konci řádku je středník, operandy instrukcí se musejí psát do závorek a navíc jsou v opačném pořadí.
- TASM - Turbo Assembler - Možná pamatujete starší překladač od firmy Borland. Byl vyvíjen v letech 1989-1996. Turbo Assembler podporuje jen tvorbu 16 a 32bitových programů. V určitém režimu lze TASM použít jako MASM.
- LZASM - je kompatibilní s TASM, ale na rozdíl od TASM je zdarma a podporuje novější procesory.
- Yasm - Modular Assembler Project - vychází z NASM, ale umí i syntaxi GAS. Vývoj skončil v roce 2014.
- A86 - jeden z nejstarších kompilátorů. Ke stažení je pouze 16-bitová trial verze pro DOS. (32-bitovou verzi autor nabízí za 82 dolarů).
Pro operační systém Windows jsou nejlepšími kompilátory Asmc a UASM. Ostatní kompilátory neumožňují program ladit, neobsahují hlavičkové soubory systémových funkcí, nebo nepodporují 64-bitové aplikace. Pro operační systém Linux jsou nejlepšími kompilátory NASM a FASM. Pro NASM existuje více návodů a je na Linuxu hodně rozšířený. Naopak FASM je méně známý, ale nabízí pokročilejší funkce.
My budeme v tomto kurzu používat kompilátor NASM pro 16-bitové aplikace pro DOS a kompilátor UASM pro 32-bitové a 64-bitové aplikace pro Windows. Volba je čistě osobní a v budoucnu si můžete vyzkoušet i další kompilátory.
NASM
NASM si stáhněte na https://www.nasm.us/
NASM za nás tedy vlastně převede slova do strojového kódu. Stažení a instalaci jistě zvládnete. Pro překlad našich programů můžeme použít příkazový řádek (CMD). Ještě efektivnější ale bude napsat si pomocný soubor ve skriptovacím jazyce Batch. V kurzu budeme překládat pro Windows, na Linuxu si určitě zvládnete vytvořit analogický Bash skript.
Vytvoření prvního ASM projektu
Nejprve si někde vytvoříme novou složku Assembler/
pro
všechny naše projekty. Zde uděláme podsložku Tools/
. Do
složky Tools/
vložíme stažený NASM a vrátíme se o složku
zpět.
Tam vytvoříme složku HelloWorld/
, což je projekt, který
nyní budeme programovat. Uvnitř HelloWorld/
vytvoříme ještě
dvě poslední složky. Nejprve Source/
a poté
Bin/
.
Sestavení
Nyní otevřeme editor a vložíme do něj tento kód v Batch:
echo off title Assembling... cls echo Assembling Hello, World!... ..\Tools\nasm.exe -fbin -o Bin\hlwrld.com Source\hlwrld.asm echo. pause exit
Soubor uložíme jako Sestavit.bat
ve složce
HelloWorld/
. Takto nebudeme muset pro každou kompilaci opakovaně
psát do příkazového řádku, ale jen otevřeme soubor.
Možná jste si všimli zkráceného názvu hlwrld
.
To je proto, že tento program budeme spouštět v 16-bitovém emulátoru, kde
je název souboru omezený na 8 znaků.
Registry a přerušení
Pro programování v ASM je nutné používat registry a přerušení. Pojďme si je vysvětlit.
Registry
Již minule jsme si zmínili, že registry jsou rychlá paměť přímo v procesoru a budeme s nimi pracovat velmi často. Jsou to vlastně takové předpřipravené proměnné, přímo vypálené v křemíkové destičce procesoru, kterých je samozřejmě omezený počet.
Tyto proměnné se používají na klíčových místech našich programů, předáváme přes ně např. argumenty funkcím, ukládáme tam počítadlo cyklů a podobně. Kdyby bylo kvůli těmto operacím potřeba posílat data do paměti RAM, byl by program zbytečně pomalý. Stejně, jako paměť RAM ulevuje pevnému disku z výkonnostních důvodů, registry a cache v procesoru ulevují paměti RAM.
Registry Intel 8086
Dlouho měly registry 32 bitů, dnes jsou i větší. Různé registry mají různá označení a účel. U prvního Intel procesoru z rodiny x86, 8086, byly všechny registry 16bitové a byly rozdělené do následujících kategorií:
- Univerzální registry (General purpose registers)
- Indexové (Index registers)
- Stavové a kontrolní (Status and Control registers)
- Segmentové (Segment registers)
Během kurzu si je podrobně vysvětlíme. Vidíme, že nutnou podmínkou k programování v ASM tedy není jen znalost ASM, ale i znalost architektury x86.
Tyto registry dále existují i v současných PC, jen samozřejmě přibyly další modernější standardy, příkladem může být technologie MMX Pentií a další.
Přerušení
Registry jsou tedy vlastně proměnné v procesoru. A na co potřebujeme přerušení? Při vykonávání programu se musí také obsluhovat určité hardwarové a softwarové události. Za hardwarové události můžeme považovat například stisk klávesy nebo pohyb myší. Za softwarové například ovládání klávesnice a myši. Při takovém přerušení dochází k přerušení právě prováděné úlohy, ke které se procesor později vrátí. Od toho tedy název přerušení, anglicky interrupt.
Mechanismus přerušení je následující:
- Řadič přerušení dostane žádost o přerušení
- Mikroprocesor přijme signál o přerušení
- Řadič přerušení vyšle na datovou sběrnici instrukci
INT
+ číslo - Proběhne obsluha přerušení
- Procesor se vrací k původní úloze s obnovenými registry
Instrukce INT
má jediný parametr. Tento
parametr je číslo v rozsahu 0
až
255
. Podle čísla se provádí určitá hardwarová
přerušení. Důležitou informací ale je, že ne všechna tato
čísla jsou obsazena hardwarovými přerušeními, ale i službami, kterými
jsou právě již zmíněná softwarová přerušení. Jako příklad
si můžeme opět uvést známé přerušení INT 21H
, které
nalezneme v operačním systému MS-DOS nebo
INT 80H
, které nalezneme v Linuxu. Některá
softwarová přerušení, která budeme používat, nám nabízí přímo
BIOS (např. video-přerušení INT 10H
). To
použijeme k výpisu znaků na obrazovku.
A co dělá v přerušení písmeno H
? Přerušení
typicky zadáváme jako číslo v šestnáctkové (Hexadacemální) soustavě.
INT 10H
je tedy přerušení číslo 16.
Z pohledu vyšších programovacích jazyků jsou přerušení ekvivalentem rozhraní, s kterými můžeme z našich programů pracovat, podobně jako třeba knihovny.
Protože se budeme zabývat i psaním vlastního operačního systému,
nebudeme používat přerušení, která nabízí jiné operační systémy
(například MS-DOS - INT 21H
a Linux - INT 0x80
). To
ale neznamená, že se jim úplně vyhneme. Později si ukážeme, jak napsat
aplikaci pro MS-DOS a Windows, abychom pochopili, jak je tomu u již
existujících operačních systémů.
Postupně se dostaneme i k tvorbě vlastních přerušení, ale tím vás zatím děsit nebudu
Těchto kódů budeme využívat při tisknutí znaků pomocí přerušení BIOSu.
V příští lekci, Assembler - První program - Hello world!, naprogramujeme svou první aplikaci v Assembleru, vypisující text Hello world! do videopaměti.