Tyto instrukce jsou dobrým pomocníkem každému, kdo je umí používat. Jedná se o bitový posuv uvnitř slabiky, nebo slova. Počet bitů posuvu je specifikován použitým registrem, nebo označením paměťového místa.
Posuvy:
Rotace:
Kontrola jednotlivých
bitů
Jestliže potřebujeme zkontrolovat, jakou hodnotu
některý z bitů nese, stačí slovo nebo slabiku rotovat přes
registr CF. Hodnotu, kterou bit nese, potom zjistíme kontrolou
registru CF.
Tvorba masky
Jestliže nevíme, jak vytvořit slabiku nebo slovo pro
vymaskování, použijeme instrukci posuvu. MOV AL,
1; SHL AL, 3. Takto získáme slabiku s
nastaveným bitem na čtvrtém místě (00001000).
Celočíselné dělení
mocninou 2 a násobení konstantou
Je to nejdůležitější použití posuvů. Vychází z
faktu, že bitový posuv čísla doleva o jeden krok je stejný,
jako bychom číslo vynásobili dvěma. Naopak bitový posuv
čísla doprava o jeden krok je stejný, jako bychom číslo
dělili dvěma. Dělení: Do registru umístíme dělence. Ten
potom posuneme doprava o tolik, kolikátou mocninou 2 je
dělitel:
Pozor! Toto dělení je sice velmi
rychlé, ale použitelné jen tehdy, jestliže chceme číslo
dělit mocninou 2 (a to bývá naštěstí nejčastěji). Ke
zjištění zbytku po celočíselném dělení použijeme operaci
AND (jak bylo popsáno výše).
Násobení čísla konstantou: Do tolika registrů, kolik je log.
1 v binárním vyjádření konstanty, umístíme hodnotu
čísla. Potom jednotlivé registry posuneme doleva. Každý o
tolik, na kolikátém místě byla log. 1 v binárním
vyjádření konstanty. Nakonec všechny registry přičteme k
jedinému, ve kterém bude výsledek.
Příklad: Vynásobme konstantou 18 vložené číslo:
Logická 1 je tedy na místě č.1 a č.4. Proto použijeme dva registry, ty posuneme o 1 a 4 kroky. Nakonec je sečteme.
{$G+}
var cislo:word;
begin
readln (cislo);
asm
MOV
AX,cislo
{naber číslo do prvního registru}
MOV
BX, AX
{naber číslo do druhého registru}
SHL
AX, 1
{v prvním registru jednou doleva<=>vynásob 2}
SHL
BX, 4
{v druhém registru čtyřikrát doleva<=>vynásob
16}
ADD
AX, BX
{sečti obsahy obou registrů}
MOV
cislo, AX
{vrať přes proměnnou cislo}
end;
writeln ('Číslo*18=',cislo);
end.
Uvedený postup můžete snadno převést na libovolnou konstantu. Vzhledem ke zdlouhavosti násobení instrukcí MUL vám tento algoritmus občas zrychlí program.
Následující příklad vytváří řetězec informací o čase. Ten si zjistí z paměti CMOS. Čtení provádíme tak, že na adresu portu $70 vyšleme číslo čtené slabiky (0 - sekundy, 2 - minuty, 4 - hodiny) v CMOS. Z portu $71 potom přečteme její hodnotu. Ta je v CMOS ve zhuštěném BCD tvaru. Proto ji převedeme na nezhuštěný a teprve potom na kód ASCII. Nakonec data zapíši do proměnné slovo typu string ve tvaru, v jakém je zvykem čas zapisovat. Program jsem optimalizoval tak, aby měl co nejmenší počet instrukcí. Vzhledem k tomu, že ve vloženém assembleru jsem nepoužil cyklus, tvořím jej s pomocí pascalovského for cyklu. Podobným způsobem bychom četli i jiné užitečné informace z paměti CMOS (datum, konfigurace . . .).
Příklad:
uses crt;
var i:byte;
slovo:string;
begin
slovo[0]:=#8;
slovo[3]:='.';
slovo[6]:='.';
clrscr;
repeat
for i:=0 to 2 do
asm
MOV
BX,offset
slovo {naber adresu proměnné slovo do BX}
XOR
AH,AH
{vymaž horní polovinu registru AX}
MOV
AL,i {naber do dolní poloviny AX krok i}
SUB
BX,AX
{odečti od BX obsah AX}
SHL
AL,1
{vynásob, AL:=AL*2}
SUB
BX,AX {odečti od BX obsah AX}
OUT
$70,AL
{pošli na CMOS adresu čtené slabiky}
IN
AL,$71
{přečti z CMOS obsah čtené slabiky}
MOV
AH,AL
{zkopíruj obsah přečtené slabiky do AH}
SHR
AH,4
{desítky posuň do dolní poloviny AH}
AND
AX,$0F0F
{odstraň zbytečné bity}
OR
AX,$3030
{proveď převod do ASCII}
MOV
8[BX],AL
{nastav jednotky v proměnné slovo}
MOV
7[BX],AH
{nastav desítky v proměnné slovo}
end;
gotoxy (1,1);
write(slovo);
until keypressed;
readkey;
end.