Základy nízkoúrovňového programování

Doteď jsme se snažili program co nejvíce přiblížit nám, lidem, ale počítač se nám může přizpůsobit jenom trochu. Člověk se přizpůsobí všemu, a tak se v programování může přiblížit jazyku, který používá samotný počítač. Získá tak kontrolu nad tím, co dělá procesor, jak je využita paměť a nezatěžuje počítač žádnými zbytečnými příkazy.

Tento způsob programování je velice náročný na pochopení.

Nejdříve se podívejme na pár veledůležitých slovíček:

příkaz - povel počítači, co má dělat
paměť - místo, kde jsou uložena data (informace a další instrukce)
instrukce
- povel samotnému procesoru
registr - vnitřní paměť procesoru
assembler - jazyk, ve kterém se píší nízkoúrovňové programy (nechceme-li je psát přímo ve strojovém kódu - to je to, co vidíte, otevřete-li spustitelný *.exe soubor v poznámkovém bloku)

Skoky

Skok - tento příkaz skočí na dané návěští (to může být téměř kdekoliv...)
Používáme-li skoky neuváženě, můžeme vyrobit natolik nepřehledný program, že se v něm nevyzná nikdo, natož pak my...
Skoky jsou tedy zrádnou součástí programování. Většinou je lze nahradit (použitím vhodných cyklů, vhodného větvení, využíváním booleovských výrazů, procedur pro řízení programu...). Ale občas se hodí.
V assembleru to bez skoků skoro nejde.

K praxi (nejprve se koukneme, jak na skoky v obyčejném Pascalu):
Pomocí label Návěští1, Návěští2, ...; si nadefinujeme návěští.
Poté je umístíme na daná místa kódu (Návěští:)
No a skok na ně provedeme pomocí goto Návěští.

Raději na nepraktickém příkladu:

program Neprehlednost;
{Tento program slouží pouze jako ukázka toho, jak může nevhodné či nadměrné
používání skoků zamlžit smysl programu}
label A,B,C,D;
begin
 goto D;
 A:goto C;
 B:writeln('To je na nic');
 goto A;
 C:writeln('Prehlednost nade vse');
 D:goto B;
end.

Architektura procesoru

Procesor obsahuje vlastní jednotku na zpracování instrukcí (ta se dále dělí, ale to není podstatné) a
vnitřní paměť (registry).

Registrů je celá řada. Nejdůležitější jsou: EAX, EBX, ECX, EDX, CS, DS.

Registry EAX, EBX, ECX, EDX

Tyto registry jsou 32-bitové a slouží k ukládání dat.

Dolních 16-bitů EAX se nazývá AX.
8 horních bitů AX = AH
8 dolních bitů AX = AL

Podobně je tomu u registrů EBX, ECX, EDX. Celkem tedy rozlišujeme tyto datové registry :
EAX, AX, AH, AL, EBX, BX, BH, BL, ECX, CX, CH, CL, EDX, DX, DH, DL,

V Pascalu se ovšem z 32-bitových registrů využívají pouze jejich dolní části (AX, AH, AL,...)

Implementace assembleru v Pascalu

Chceme-li vložit do našeho programu blok kódu, který je psán nízkoúrovňově, poslouží nám k tomu
asm
Instrukce
Instrukce
...
end;

Naučme se nyní pár instrukcí:
mov cíl, zdroj Totéž, co Cil:=Zdroj; v Pascalu. Zdroj může být paměť (=proměnná) , konstanta, nebo registr. Cíl je buďto paměť nebo registr (Nejde přesunovat z paměti do paměti).
add cíl, zdroj v Pascalu : Cíl:=Cíl+Zdroj; o Cíli a Zdroji to samé

Aby to bylo zcela jasné :
program Scitani;
var A,B,C:Integer;
begin
 asm
  mov AX,15
  mov A,AX
  mov BX,11
  add BX,AX
  mov B,BX
  mov CX,11
  mov C,CX
 end;
 Writeln(A,B,C);
end.

Přerušení je krátká procedura operačního systému, která se spustí, stane-li se něco výjimečného. Lze zavolat i pomocí INT xx: volej přerušení xx.
Některá přerušení žádají dodatečné informace, ty musíme uložit do požadovaných registrů předtím než zavoláme INT xx.
Některých přerušení zase poskytují v registrech výsledek.

Co které přerušení dělá? Chcete-li mít kompletní seznam, nezbývá vám, než si odněkud z Internetu stáhnout Sysmana (systémový manuál, sysman.com). Existují i jiné helpy, ale v Sysmanovi je všechno potřebné (a navíc je česky).

Podívejme se alespoň na pár přerušení.

int 33h - přerušení myši.
Zde naleznete všechno potřebné pro ovládání myši.
Toto přerušení obsahuje řadu funkcí. Ovládá se jednoduše:
Do AX uložíme číslo příslušné služby. (A do ostatních registrů další potřebné hodnoty)
Zavoláme Int 33H.
A pak si přečteme zjištěné hodnoty v některých registrech.

Služba Vstup Vrací
00h - inicializace myši nic AX=0, když myš není nainstalována, jinak AX>0.
BX - počet tlačítek myši
01h - zapni kurzor nic nic
02h - vypni kurzor nic
03h - zjisti stav myši nic BX - stav tlačítek,CX- X-ová souřadnice kurzoru (jako v graf. režimu) DX- Y-ová souřadnice
04h - nastav stav myši CX x-ová souřadnice
DX y-ová souřadnice
05h - stav stlačení tlačítka BX - tlačítko (0-levé,1-pravé,2-prostřední) AX - stav všech tlačítek
BX - počet všech stisknutí daného tlačítka od posledního volání funkce 05h
CX - horizontální souřadnice při posledním stisknutí
DX - vertikální souřadnice při posledním stisknutí
06h - stav uvolnění tlačítka BX - tlačítko jako u 05h, pouze
BX - počet uvolnění tlačítka
Takže např.
var PocetTlacitek : Integer;
asm
 mov AX,0
 int 33h
 mov PocetTlacitek,BX
 int 01h
end; 

Zapne kurzor a zjistí počet tlačítek...
Assembler se používá:

Pokud se nám stane, že některá námi používaná procedura je celá psaná v assembleru, je lepší ji nadefinovat jako assembler proceduru(popř. funkci):
procedure Nahod(parametry);assembler;
label ...;
type ...;
var ...;
asm
end;

Všimněte si, že zde chybí begin !! (části label, type a var můžou také chybět).
U funkcí se návratová hodnota ukládá do AX (EAX). (Tedy žádný název funkce)

To by bylo pro dnešek vše.
DCV: Pokud máte počítač, který podporuje přerušení DOSu (tedy Windows či MS-DOS), sežeňte si Sysman. Podívejte se také na nějaký kvalitní kompilátor (anglicky compiler) pro assembler (např. MASM 32)