Operátory slouží k provedení nějaké operace s danou hodnotou. Příkazy naproti tomu donutí počítač něco dělat.
Tento příkaz je velmi jednoduchý : ; (ano skutečně jen jeden středník)
Tento příkaz nic nedělá. Lze ho napsat všude tam, kde by mohl být jiný příkaz. Nejčastěji se používá při ladění (for I:=1 to 10 do ; begin, zde tento příkaz vyřadí for z provozu). Dále pak v některých situacích zvyšuje přehlednost a přenositelnost programu (za posledním příkazem před endem se středník nepíše, když ho tam však napíšeme, jedná se o prázdný příkaz a nic se nestane. Je to výhodné - později budeme moct za tento příkaz psát, aniž bychom ten středník dodělávali.)
Tento příkaz je také jednoduchý Proměnná := Výraz;
Nejprve se vyhodnotí výraz a jeho hodnota se přiřadí dané proměnné. Její původní hodnota se ztratí. Je tedy možné např. přiřazení A:=A+1.7;
NazevProcedury;
Také se jedná o velice jednoduchý příkaz. Můžeme využít předem
definované procedury, či si definovat své vlastní.
goto Návěští;
Příkaz skoku. Po provedení toho příkazu přeskočí program na dané místo
(vynechá některé příkazy, či se někam vrátí). Všechna návěští musíme definovat v
sekci label, v kódu je pak vyznačíme takto Název:
Raději na konkrétním příkladě :
program Skace; label SkocSem; begin SkocSem: write('Haha'); goto SkocSem; end.
Názvy návěští smí být maximálně čtyřmístná kladná čísla, či libovolné identifikátory. Není povolen skok dovnitř do bloku nebo ven z bloku (Do a z podprogramu, procedury, funkce,..). Může se skákat do složeného a ze složeného příkazu (což ovšem značně znepřehlední program). Skoku se sice lze vždy vyhnout, za zvlášť nepříznivých okolností je ale jeho použití nejjednodušší a nejpřehlednější formou řešení (a pouze v takovýchto případech se vyplatí)
Efektivní využití goto je možné pouze v podmíněném příkazu a příkazu vícenásobného větvení. (Zamyslete se nad tím, proč je jinde tento příkaz zbytečný).
Inline(Cislo[/Cislo]...);
Nejprve krátce k syntaxi : Parametr Inline tvoří
čísla (nejčastěji v hexadecimální podobě - tedy s $
před sebou), která jsou oddělena lomítkem (v případě jednoho čísla lomítko
nepíšeme).
Tento příkaz umožňuje vložit do našeho programu instrukce procesoru (vloží dané
slabiky přímo do kódu našeho programu). Nesprávné použití zkolabuje počítač
(Windows tedy skoro jakékoliv použití zakazují).
Chceme-li z daného čísla využít jen jednu (první) slabiku (=byte), použijeme
unární operátor < (Ten dané číslo zkrátí na
jednu jedinou slabiku). Chceme-li naopak z jednoho bytu vytvořit slabiky
dvě, použijeme operátor > (Jako druhou slabiku
generuje 00);
Tedy např.
Inline($FA); - Tato instrukce zakáže hardwarové
přerušení.
Inline(<$13A7/>$3A);
Vloží do výsledného kódu byty $A7 (skutečně, vzhledem
k uložení v paměti je A7 první slabikou čísla 13A7 :), $3A
$00 (> doplní nulami);
Pomocí Inline lze využít i instrukce procesoru, které standardní Pascal nezná (Např. instrukce MMX). Podívejte se do Sysmana, na tabulku instrukcí (která slabika odpovídá které instrukci assembleru.)
Tzv. strukturované příkazy se vyznačují tím, že v jejich definici se objevuje více rezervovaných slov, která jsou od sebe nějakým způsobem oddělena.
begin Příkaz1; Příkaz2; ... PrikazPosledni end;
Nejjednodušší strukturovaný příkaz. Slouží především tam, kde je z důvodu syntaxe nutné použít příkaz jediný a my jich tam potřebujeme vměstnat více (např. u cyklů či podmíněných příkazů). Za posledním příkazem před endem není středník (my ho tam ale psát budeme, středník se vyhodnotí jako prázdný příkaz a pokud budeme chtít později něco připsat, nebudeme muset na ten středník myslet.)
asm Instrukce1 Instrukce2 ... InstrukcePosledni end;
Tento příkaz umožňuje vložit instrukci assembleru do našeho kódu. Překladač umí zpracovávat instrukce I2086 a některé další (všechny novější procesory tyto instrukce podporují). Všimněte si, že za instrukcemi není uveden středník (i když pochopitelně tam prázdný příkaz napsat můžeme).
Podívejme se nyní na to, co překladač pascalský překladač assembleru zvládá. Rozlišuje tyto registry (AX, BX, CX, DX, AL, AH, BL, BH, CL, CH, DL, DH; dále CS, DS, ES, SS, IP, SI, DI, SP, BP a pochopitelně všechny vlajky).
Při psaní instrukcí pamatujte na to, že maximálně jedna hodnota
smí být z paměti (u mov), zbytek musí být registry !!!
Seznam nejdůležitějších instrukcí (podívejte se do Sysmana) :
Pořadí | Instrukce | Význam |
---|---|---|
1 | ADD dest, src | Sečte dest + src a výsledek uloží v dest |
2 | INC dest | Zvýší dest o jedna |
3 | SUB dest, srt | Odečte dest - src a výsledek uloží v dest |
4 | DEC dest | Sníží dest o jedna |
5 | CMP dest, src | Porovná dest a src (nedestruktivně odečte a nastaví vlajky) |
6 | NEG dest | Změní znaménko Dest |
7 | MUL src | Násobí, je-li src 8-bitové, násobí AL*src a výsledek uloží do AX, je-li src 16-bitové násobí AX*src16 a výsledek uloží do AX:DX |
8 | DIV src | Opak násobení, zbytek po celočíselném dělení uložen v AH (je-li src 8bitový), či v DX (je-li src 16-bitový) |
9 | AND dest, src | Bitově znásobí dest a src a výsledek uloží do dest |
10 | TEST dest, src | Bitově znásobí dest a src (nedestruktivně) a podle výsledku nastaví vlajky |
11 | OR dest, src | Bitově logicky sečte dest a src a výsledek uloží do dest |
12 | XOR dest, src | Bitově exkluzivně sečte dest a src a výsledek uloží do dest |
13 | NOT dest | Bitově zneguje Dest (přehodí bity na opačné) |
Pořadí | Instrukce | Význam |
---|---|---|
1 | SHL dest, count | Bitový logický posun doleva, Count je 1, nebo CL (s 1 je instrukce mnohem rychlejší) |
2 | SHR dest, count | Bitový logický posun doprava, Count je 1, nebo CL (s 1 je instrukce mnohem rychlejší) |
Pořadí | Instrukce | Význam |
---|---|---|
1 | MOV dest, src | Přemístí hodnotu src do Dest (ale ne z paměti do paměti - aspoň jeden údaj je registr nebo číslo) |
2 | XCHG dest, src | Prohodí hodnoty src a dest |
3 | IN AL(AX),port8(16) | Načte do AL (AX) data z portu port8 (16) |
4 | OUT port8(16),AL(AX) | Pošle do port8(16) data z AL (AX) |
5 | PUSH src | Uloží src nahoru do zásobníku |
6 | POP dest | Načte ze zásobníku horní hodnotu a přemístí ji do dest (registru) |
7 | PUSHA | Uloží všechny důležité registry nahoru do zásobníku (Funguje pouze, jsou-li zapnuté instrukce 286) |
8 | POPA | Načte ze zásobníku důležité registry (Funguje pouze, jsou-li zapnuté instrukce 286) |
Pořadí | Instrukce | Význam |
---|---|---|
1 | JMP kam | Skočí na kam |
2 | JCXZ kam | Je-li CX=0 skočí na kam |
3 | LOOP kam | Odečte od CX 1 a je-li CX<>0 skočí na kam |
4 | JB/JC kam | Skočí, je-li menší (po provedení CMP,..) |
5 | JE/JZ kam | Skočí, je-li rovno (po CMP,..) |
6 | JG/JNGE kam | Skočí, je-li větší (po CMP,..) |
7 | JNE/JNZ kam | Skočí, není-li rovno |
8 | INT n | Zavolá přerušení n (takový malý podprográmek, který např. obsluhuje klávesnici, myš,..) |
Pořadí | Instrukce | Význam |
---|---|---|
1 | CLI | zakáže maskovatelné hardwarové přerušení |
2 | STI | povolí maskovatelné hardwarové přerušení |
if Podminka then Prikaz;
if Podminka then Prikaz1 else Prikaz2;
Chceme-li, aby se nějaký příkaz vykonal pouze v případě, že je splněna jistá podmínka, použijeme tento, tzv. podmíněný příkaz. Prikaz (Prikaz1) se vykoná, jestliže daná podmínka má hodnotu true. Prikaz2 (Větev else) se naopak vykoná pouze v případě, že daná podmínka má hodnotu false.
Podmínka = libovolný výraz, jehož výsledným typem je Boolean
Prikaz - jeden jediný příkaz, chceme-li aby se vykonala sada příkazů, musíme
použít příkaz složený (či definovat vlastní proceduru)
case OrdinarniPromena of Hodnota1:Prikaz1; Hodnota2:Prikaz2; ... end; case OrdinarniPromena of Hodnota1:Prikaz1; Hodnota2:Prikaz2; ... else PrikazJinak; end;
Potřebujeme-li vykonat nějaký příkaz podle toho, jakou hodnotu má jistá
ordinální proměnná, použijeme tento příkaz. V případě, že daná ordinální
proměnná nabývá Hodnoty1, provede se Prikaz1 (zase jen jeden příkaz -
nejčastěji tedy příkaz složený), v případě, že nabývá Hodnoty2, provede se
Prikaz2. V případě, že nenabývá žádných z uvedených hodnot, provede se větev
else (PrikazJinak). Větev else pochopitelně nemusí být uvedena
(stejně tak jako u podmíněného příkazu if...then...)
Case se používá, je-li daných hodnot více než dvě (pro jednu
či dvě možné hodnoty je výhodnější použít if...then a if...then...else...)
Pochopitelně je možné použít více hodnot naráz :
case A of 1..6 : Writeln('A je mensi nebo rovno sesti'); 1,3,5,7,9 : Writeln('A je licha cislice'); 8 : Writeln('A je suda cislice vetsi nez sest'); else Writeln('A neni cislice); end;
Vždy se vykoná jeden jediný příkaz, je-li tedy např. A=1, pak se napíše pouze, že jde o číslo menší rovno šesti, to že se jedná o číslo liché se nenapíše.
Pro úplnost poznamenejme, že dané ordinální proměnné se říká
selektor a že maximální rozsah selektoru je 65536 hodnot.
Příkaz vícenásobného větvení bývá občas také nazýván přepínačem.
Chceme-li, aby se určitý úsek kódu opakoval, použijeme cykly. V Pascalu rozlišujeme tři typy cyklů. Nejuniverzálnějším cyklem je cyklus while. Těla cyklů mohou obsahovat standardní procedury Break a Continue.
Break - okamžitě ukončí cyklus a skočí za něj
Continue - skočí k podmínce a znovu ji vyhodnotí (prostě vynechá všechny
příkazy, až do konce cyklu)
Pomocí těchto příkazů se lze vyhnout většině skoků.Nemusím snad připomínat, že (podobně jako u goto) je jejich efektivní použití možné pouze za if či case.
while Podminka do Prikaz;
Pokud je Podminka=true, prováděj příkaz.
Jako obvykle je Podminka libovolný výraz s výsledným booleovským typem. V
průběhu Prikazu (těla cyklu) pak musíme zajistit, aby se hodnota Podminky
měnila, jinak se program "zacyklí" - bude cyklus opakovat neustále dokola
(nevyskočíme-li z něho někde pomocí Break).
V případě, že je podmínka=false, cyklus se neprovede ani jednou.
Současné událostní programování lze pomocí tohoto cyklu přenést i do Pascalu. Prostě celý program uzavřeme do while, neustále testujeme co se děje, stane-li se něco důležitého, zavoláme příslušnou proceduru (která třeba donutí ukončit program, tím, že změní podmínku cyklu...)
Pomocí while je také možné naprogramovat všechny ostatní cykly.
repeat Prikaz1; Prikaz2; ... PrikazPosledni until Podminka;
Příkazy v těle cyklu repeat se provedou a není-li na konci cyklu splněna podmínka, opakuje se celý cyklus repeat od začátku. Oproti while má tu výhodu, že příkazy se provedou alespoň jednou.
Všimněte si dále, že za posledním příkazem před until zase nemusí být středník. (Ale my ho tam psát budeme).
Cyklus repeat se nejčastěji používá ke kontrole uživatelem zadaných dat, nejsou-li údaje v pořádku, ať uživatel zadává, dokud se mu to konečně nepovede...
for OrdinalniPromenna := Zacatek to Konec do Prikaz;
for OrdinalniPromenna := Zacatek downto Konec do Prikaz;
Nejjednodušší cyklus. Daná ordinální proměnná při něm nabývá
hodnot Zacatek do Konec. (Zaciname-li s Zacatkem vyšším než Konec, je nutné
napsat downto, jinak se cyklus neprovede).
V těle cyklu zásadně neměníme hodnotu dané OrdinalniPromenne - mohlo by to vést
ke kolapsu programu či jeho zacyklení.
Z pochopitelných důvodů je Prikaz nejčastěji příkazem složeným.
Vyzkoušejte si to raději na konkrétním příkladu :
for Znak:='a' to 'z' do Write(Znak); for Cislice=9 downto 0 do begin Writeln(Cislice); Writeln('Zbytek po deleni sedmi je : ', Cislice mod 7); end;
Chceme-li proměnnou měnit při každém průchodu cyklu třeba o 2 a ne o 1, máme dvě možnosti : pomocí if ... then Continue přeskočit nežádoucí cykly (což je pěkná blbost, ale jde to) nebo si zadefinovat jinou proměnnou a na začátku každého cyklu ji změnit o požadovanou hodnotu.
with Nazev do Prikaz;
with Nazev1, Nazev2,... do Prikaz;
Tento příkaz slouží k usnadnění práce. V průběhu příkazu nemusíme neustále
dokola vypisovat Nazev., Nazev1. či Nazev2. ,... překladač
sám zajistí, aby se tyto názvy doplňovaly. V případě, že takto jsou takto
zpřístupněné dvě proměnné stejného názvu, záleží na kompilátoru, kterou z nich
zvolí (nejčastěji to bude posledně uvedený název).
Efektivní použití with je očividně možné pouze s využitím složeného příkazu (kvůli jednomu příkazu se nám with nevyplatí).
Příklad:
var Pracovnik:record Jmeno:string; Vek:Byte; Plat:Longint; end;
Dite:record Jmeno:string; Vek:Shortint; end; begin Pracovnik.Jmeno:='Leos'; with Pracovnik do begin Jmeno:='Igor'; Vek:=34; Plat:=9863; end; with Pracovnik, Dite do begin Jmeno:='Alena'; Vek:=15; Plat:=10000; end; Writeln('Dite : ', Dite.Jmeno, '/', Dite.Vek); {I zde by bylo pouziti with vyhodnejsi} Writeln('Pracovnik : ', Pracovnik.Jmeno, '(',Pracovnik.Vek,') / ', Pracovnik.Plat); end.
To je pro dnešek vše. Nic si z toho nedělejte, pokud vám nejsou jasné příkazy inline a asm (a zbytek je v pohodě). Bylo to přece jen takové lehké opakování.