Učebnice Assembleru 86

Instrukce logických operací

Logické instrukce jsou jednou z dobrých pomůcek programátorů. ASM86 je schopen provádět všechny běžné logické operace, a to se slovem nebo slabikou. Chybí zde tedy instrukce pro jednotlivé bity. Ty však volbou vhodných algoritmů můžeme lehce nahradit.

  • NOT zdroj - neguj všechny bity zdroje
  • AND zdroj, cíl - logický součin zdroje s cílem ulož do zdroje (registr - hodnota, paměť - hodnota, registr - registr, paměť - registr, registr - paměť)
  • TEST zdroj, cíl - logický součin zdroje s cílem, ale nastav jen registr příznaků F (registr - hodnota, paměť - hodnota, registr - registr, paměť - registr, registr - paměť)
  • OR zdroj, cíl - logický součet zdroje s cílem ulož do zdroje (registr - hodnota, paměť - hodnota, registr - registr, paměť - registr, registr - paměť)
  • XOR zdroj, cíl - logický vylučovací součet zdroje s cílem ulož do zdroje (registr - hodnota, paměť - hodnota, registr - registr, paměť - registr, registr - paměť)

Kolikabitová operace je, určuje opět specifikace zdroje a cíle. Instrukci TEST použijeme k nastavení příznakového registru, a tak můžeme větvit program, aniž bychom ovlivnili hodnoty zdroje a cíle.

Použití logických operací

Vymaskování slabiky nebo slova
Často potřebuje programátor nastavit některé bity slabiky, nebo slova do hodnoty log. 1, nebo 0. K tomu mu velmi dobře poslouží právě logické operace AND nebo OR. Máme-li slabiku ve tvaru XXXXAXXX v registru AL a chceme, aby bity X měly hodnotu 0 a hodnota bitu A zůstala zachována, provedeme instrukci AND AL, $08 (=00001000). Máme-li slabiku ve tvaru XXXXAXXX v registru AL a chceme, aby bity X měly hodnotu 1 a hodnota bitu A zůstala zachována, provedeme instrukci OR AL, $F7 (=11110111).

Nulování registru
Zajímavější než instrukce MOV registr,0 je nulovat pomocí XOR registr, registr. Efekt je stejný, doba vykonání operace je kratší.

Zjištění zbytku po celočíselném dělení mocninami 2
Kdybychom vždy, když chceme zjistit zbytek po dělení mocninami 2 (a ten často potřebujeme) používali instrukci DIV, program bychom zdržovali. Stačí si jen uvědomit, že můžeme zjistit hodnotu bitů v řádech za log. 1 v binárním tvaru dělence. Chceme-li zjistit zbytek po celočíselném dělení 2 (sudé, liché číslo) čísla v registru AL, stačí jen použít instrukci AND AL,1. V registru AL je potom jen buď 1 (liché číslo), nebo 0 (sudé číslo). Pro lepší orientaci poslouží přehled:

  • AND AL, 1  ( 1 = 00000001) -> AL := AL mod 2 ( 2 = 00000010)
  • AND AL, 3  ( 3 = 00000011) -> AL := AL mod 4 ( 4 = 00000100)
  • AND AL, 7  ( 7 = 00000111) -> AL := AL mod 8 ( 8 = 00001000)
  • AND AL, 15 (15 = 00001111) -> AL := AL mod 16(16 = 00010000)

Převod čísla v nezhuštěném BCD na ASCII
Velmi jednoduchým prostředkem, jak převést číslo v rozsahu 0-9 do hodnoty jeho znaku v tabulce ASCII, je logický součet s číslem $30 (to je stejné jako přičtení 48). Použitím této úpravy čísel v kódu BCD je zobrazení i velkých čísel jednoduché.

Příklad:

var slabika:byte;
       znak:char;
begin
 repeat
  readln (slabika);
 until slabika in [0..9];
 asm
  MOV AL, slabika {do registru AL předej hodnotu slabiky}
  OR AL, $30      {převeď na ASCII}
  MOV znak, AL    {do proměnné znak předej ASCII hodnotu čísla}
 end;
 writeln (znak);
end.

V příkladu je načtené číslo z intervalu 0..9 převedeno do ASCII s pomocí log. instrukce OR.

Před dalším příkladem si musíme vysvětlit, jak ukládá Pascal řetězce (typu string). Za řetězec je zde považováno pole slabik, které má na prvním místě délku řetězce a na dalších místech jsou kódy ASCII zapsaných znaků. Informace o délce řetězce je důležitá pro jeho správné zobrazení. Ten proto nemusí obsahovat speciální ukončovací znak.

Příklad:

var slovo:string;
        i:byte;
begin
 for i:=0 to 9 do
 asm
  MOV DI, OFFSET slovo {do registru DI ulož adresu proměnné slovo}
  INC DI               {posuň se až za slabiku délky řetězce}
  XOR AH,AH            {nuluj AH}
  MOV AL,i             {do AL vlož krok i}
  ADD DI,AX            {přičti krok k adrese (posuv po řetězci)}
  OR AL,$30            {převeď obsah AL na ASCII znak}
  MOV [DI],AL          {přesuň znak do řetězce}
  INC BYTE PTR [OFFSET slovo]{zvyš délku řetězce}
 end;
 writeln (slovo);
 readln;
end.

Tento příklad vytvoří slovo typu string s čísly od 0 do 9. To, že zatím nevíme, jak se v ASM86 tvoří cykly, není na závadu. Prostě si pomůžeme znalostmi z Pascalu.

Kódování
Každý rád chrání svá data před neoprávněným přístupem kódováním. K tomu dobře slouží logická operace XOR. Postup kódování naznačuje postup. Provedeme-li operaci XOR s konstantou a kódovaným číslem, získáme kódované číslo. Pokud s kódovaným číslem provedeme opět XOR se stejnou konstantou, získáme zpět původní číslo. Čísla kódovaná přidáme do EXE souboru programu. Před jejich použitím je dekódujeme. Protože tato čísla mohou nést např. jméno autora (v ASCII), je jméno pro běžného uživatele po zakódování nečitelné (a tedy lehce nepřepsatelné v souboru EXE). Pozor! Hodnota konstanty musí být při kódování i dekódování stejná. Tento postup můžeme libovolně pozměňovat podle úrovně našich znalostí (např. xorovat první znak s druhým, druhý s třetím, . . .).

Směr