Obsah    Kapitoly: 12345678,  |  X.1X.2X.3X.4,  |  Y1 Y2 

8) Aritmetické instrukce

8.1) Násobení dělení, sčítání a odčítání

Řekl bych, že v assembleru už pár věcí zvládnete, ale ještě jsem se nezmínil o tak zásadní věci, jako je sčítání, násobení apod. Tak to nebudeme dlouho protahovat a jdeme rovnou k věci:

  • Instrukce ADD

    Syntaxe:
            ADD < kam >, < co >        
    Jednoduše provede následující:
    < kam > := < kam > + < co >
    Pokud je výsledek větší, než je možno uložit, neboli, byl by třeba ještě jeden bit k uložení čísla, nastaví se vlaječka Carry (CF) na 1. Např:
    MOV AH,FFH                   ;AH:=255 (FFH)
    ADD AH,1
    Výsledek je 256, což se do AH nevejde(max. 255), proto bude AH=0, ale CF bude jedna, a pokud dáme CF před AH, takto:
    CF
    1
     7   6   5   4   3   2   1   0 
     0   0   0   0   0   0   0   0 
    tak nám bity dají skutečný výsledek, tedy 256 (nebo 100H, jak chcete).

  • Instrukce ADC (Add with Carry, sečti s CF)

    Syntaxe:
            ADD < kam >, < co >        
    A provede:
    < kam > := < kam > + < co > + CF
    Používá se při sčítání dvou 64bitových čísel. Dejme tomu, že:
    EAX:EBX - první 64bitové číslo
    ECX:EDX - druhé 64bitově číslo


    Pak je můžeme sečíst takto:
    ADD EBX, EDX
    ADC EAX, ECX


  • Instrukce INC (Increment, neboli přidej jedna)

    Syntaxe:
            INC < co >        
    Místo toho, abyste psali
    ADD AL,1
    bývalo kdysi na starších počítačích rychlejší a efektivnější napsat:
    INC AL

  • Instrukce SUB (Substract)

    Instrukce odečítá úplně stejným způsobem, jako ADD sčítá:
    Syntaxe:
            SUB < kam >, < co >        


  • Instrukce SBB (Substract with Carry, neboli odečti s carry flagem)

    Ekvivalent k ADC, ale tato instrukce naopak odčítá a bere v potas CF.
    Syntaxe:
            SBB < kam >, < co >        


  • Instrukce DEC (Decrement, odečtení jedničky)

    Opět je zde analogie s instrukcí INC, ale naopak jedničku odčítá:
    Syntaxe:
            DEC < co >        


  • Instrukce MUL (Multiply, neboli násobení)

    Syntaxe:
            MUL < co >        
    Instrukce násobí podle následujících pravidel:

    AX:=AL * < co > ;pokud je < co > 8bitové DX:AX:=AX * < co > ;pokud je < co > 16bitové

    Instrukce IMUL násobí se znaménkem, tz: 7.bit se počítá jako znaménko, pokud je 0, číslo je kladné, pokud je 1, číslo je záporné. Kvůli tomuto bitu, je maximální rozsah čísel, která se vejdou do 8bitového registru od -128(bity: 1 0 0 0 0 0 0 0) do 127(bity: 0 1 1 1 1 1 1 1). Tedy opět 255 kombinací, i když maximální číslo je o polovinu menší.

  • Instrukce DIV (Divide, dělení)

    Syntaxe:
            DIV < co >        
    Instrukce dělí takto:
    pokud je < co > 8bitové:
    AL:=AX div < co >
    AH:=AX mod < co > ;což je zbytek v AH

    pokud je < co > 16bitové:
    AX:=DX:AX div < co >
    DX:=DX:AX mod < co > ;což je zbytek v DX

    8.2) Instrukce posunů a rotací

    Tyto instrukce jsou velmi používané, a dost oblíbené hlavně tam, kde chceme zrychlit nějaký výpočet, který je jinak časově náročný. Nebudeme ale chodit okolo horké kaše a rovnou se na ně podíváme:

  • Instrukce SHL (Shift left, posun bitů vlevo)

    Syntaxe:
            SHL < co >, < o kolik >        
    Kde o kolik může být číslo, nebo CL.

    SHL < co >,1 posune každý bit v argumentu < co > o jedno doleva, přičemž nejvyšší(sedmý) bit je posunut do CF a nejnižší bit bude nahrazen 0.

    dejme tomu že:
    MOV AL, 00000001B (1D)
    SHL AL

    pak bude:
    AL:=00000010B (2D) a CF=0.

    MOV AL, 00000101B (5D)
    SHL AL

    pak bude:
    AL:=00001010B (10D) a CF=0.

    nebo
    MOV AL, 10010001B (145D)
    SHL AL

    pak bude:
    AL:=00100010B (34D) a CF=1.

    Takže tato instrukce jakoby vezme všechny bity a postrčí je všechny doleva. Ten poslední přesune do CF a prví nahradí 0.

    Ti všímavější jistě už přišli i na to, že tato instrukce jakoby vynásobí číslo 2. Z 1 na 2, z 5 na 10 a z 145 na 290 (= 34 + 256 (hodnota CF)). Pokud tedy chceme číslo násobit čtyřmi, musíme jen provést dvakrát za sebou SHL, osmi třikrát atd…

    No a teď trochu matematiky, co když chci násobit číslo 10 bez dosti zdlouhavé a časově náročné instrukce MUL?

    10 = (4+1)*2
    X*10 = X*(4+1)*2
    X*10 = (4*X+X)*2

    takže jsme si desítku rozebrali na mocniny dvou, a těmi násobit už umíme pomocí SHL, tedy posunem a bit vlevo. A pokud chci napsat X*10 v assembleru, vězte, že tomu bude takto:
    
    MOV AX, X        ; X chci násobit 10
    SHL AX, 2        ; dvakrát za sebou SHL AX což se rovná AX:=AX*4
    ADD AX, X
    SHL AX           ; AX:=AX*2
    
    dobrý co? Asi si to budete muset vícekrát přečíst, než to všechno vstřebáte, ale takto můžete velmi zrychlit násobení a dělení, pokud ovšem předem víte, kterým číslem dělit a násobit. Jinak vám totiž nezbývá nic jiného, než použít instrukci MUL

  • Instrukce SHR (Shift right, posun bitů vpravo)

    Syntaxe:
            SHR < co >, < o kolik >        
    Opak instrukce SHL. Bity, které vpravo vypadávají jsou přesunuty do CF. Místo násobení dvěma se jedná o dělení dvěma...

  • Instrukce SAL (Shift arithmetic left, posun bitů doleva se zachováním znaménka)

    Syntaxe:
            SAL < co >, < o kolik >        
    Pracuje prakticky úplně stejně, jako SHL, jenže zanechává nejvyšší (sedmý) bit, jako znaménko.

  • Instrukce SAR (Shift arithmetic right, posun bitů doprava se zachováním znaménka)

    Syntaxe:
            SAR < co >, < o kolik >        
    Jako SAL

    8.3) Logické instrukce

    Předem odkazuji na kapoitolu
    Logické instrukce, kterou byste si měli rozhodně přečíst před tím, než se pustíte do dalšího čtení.

  • Instrukce AND (Logický součin)

    Syntaxe:
            AND < kam >, < co >        
    Provede:
    < kam > := < kam > AND < co >
    A k čemu je to dobré? Používá se k nulování bitů. Tak např. chci vynulovat 1.bit v registru AL. Jak na to?
    Bit
     7   6   5   4   3   2   1   0 
    Stav
     1   1   0   1   1   0   1   1 
    co třeba AL AND 11111101? Ano, takto to funguje. Prostě tomu bitu, který nulujeme dáme hodnotu 0 a ať se procesor postará o to ostatní.
    AND
    Bit
     7   6   5   4   3   2   1   0 
    Stav
     1   1   1   1   1   1   0   1 
    =
    Bit
     7   6   5   4   3   2   1   0 
    Stav
     1   1   0   1   1   0   0   1 
    V assembleru se to dá napsat, aniž byste přemýšleli, jakou hodnotu má bit, zrovna s tou jednou nulovou hodnotou a to tak, že znegujete hodnotu bitu, který chcete nulovat:
    AND AL, NOT 2         ;2 - hodnota druhého bitu.


  • Instrukce OR (Logický součet)

    Syntaxe:
            OR < kam >, < co >        
    Provede:
    < kam > := < kam > OR < co >

    Používá se naopak pro nastavení nějakého bitu (např. nultý bit):
    OR AL, 1         ;1 - hodnota nultého bitu
    Nultý bit bude na 100% 1 a ostatní bity budou mít stejnou hodnotu, jakou měli před instrukcí OR. - pro pochopení, podívejte se do tabulky v kapitole Logické instrukce

  • Instrukce XOR (Logická nonekvivalence)

    Syntaxe:
            XOR < kam >, < co >        
    Provede:
    < kam > := < kam > XOR < co >

    používalo se dřív pro nulování čísel, protože XOR AX,AX bylo rychlejší než MOV AX,0. To se netýká už Pentií, kde je tato instrukce stejně rychlá.

  • Instrukce TEST

    Instrukce provede logický součin svých operandů (AND). Výsledek nikam neukládá, ale nastaví podle něj příznaky.
    Syntaxe:
            TEST < co >, < s čím >        


    Předchozí kapitola Nahoru Následující kapitola