Aritmetické inštrukcie


<= =>


Programátor pri svojej činnosti potrebuje nie len presuny dát. V každom programe sú nutné i výpočty a to s bežnými dátami, alebo s adresami. Tie v assembleri prevádzajú len s celými číslami. Operácie s desatinnými číslami sú zdĺhavé, i keď sú uskutočniteľné pomocou určitých algoritmov. ASM86 pre ne ale nemá inštrukcie. Väčšina matematických operácií sa prevádza s číslami v registroch alebo v pamäti. Označenie operandov je zhodné ako pri presunoch. Zároveň tieto inštrukcie nastavujú indikátory registru F. Umožnia tak vetviť program. Informácie o nastavovaných indikátoroch nájdeme v tabuľke inštrukcií (+).

Sčítanie

Pri tvorbe programu si musíme ujasniť, či chceme k cieľovému miestu pričítať 1, alebo iné číslo. Podľa toho volíme inštrukciu: Príklady:

INC AX - pričítaj k registru AX hodnotu 1
INC WORD PTR [BX] - pričítaj k slovu na adrese určenej DS:BX hodnotu 1
INC BYTEPTR CS:[adresa] - pričítaj k slabike na adrese určenej CS:adresa (konštantná) 1
SEGESINC BYTE [DI + 2] - pričítaj k slabike na adrese ES:DI + 2 hodnotu 1
ADD AX, BX - k slovu v registri AX pričítaj obsah registra BX (slovo)
ADD AH, 8 - k slabike v registri AH pričítaj číslo 8}
SEGCSADD DX, WORD PTR [BX] - k registru DX pričítaj slovo na adrese CS:BX
ADD premenná, 5 - k deklarovanej premennej pričítaj 5
ADD BYTEPTR [SI], 30 - k slabike na adrese DS:SI pričítaj 30}
ADD BYTEPTR ES:[BP], AL - k slabike na adrese ES:BP pričítaj obsah registra AL

Pokiaľ pri týchto operáciách dôjde k preplneniu cieľa, nastaví sa register OF do log. 1. Aby pri odlaďovaní vašich programov nedošlo k zbytočným hádkam s prekladačom, uvedomte si, že zdroj i cieľ musia mať rovnaký počet bitov (tzn. 8, alebo 16).

Odčítanie

Inštrukcie slúžiace k odčítaniu sú zápisom operandov zhodné s inštrukciami pre sčítanie. Preto si uvedieme len ich zoznam: Napriek tomu sú tu špecifické inštrukcie: Inštrukcia CMP porovnáva dve čísla odčítaním. Pretože ale nedôjde k ich zmene, použijeme túto inštrukciu pred vetvením programu. Za CMP totiž väčšinou nasledujú inštrukcie skoku závislé na stave príznakov registra F.
#include <stdio.h>
#include <conio.h>
int a,b,s,r;
main () {
  clrscr();            // vymaž obrazovku
  printf("a=");
  scanf("%d",&a);      // vstup hodnoty a
  printf("b=");
  scanf("%d",&b);      // vstup hodnoty b
  asm {                // začiatok bloku asm
    MOV AX, a          // do AX vlož hodnotu premennej a (z pamäte)
    ADD AX,b           // k AX pričítaj hodnotu premennej b
    MOV s, AX          // do premennej s vlož súčet z registra AX
    MOV AX,a           // znovu naber a
    SUB AX,b           // odčítaj od AX hodnotu b
    MOV r,AX           // do premennej r vlož rozdiel z registra AX
    INC a              // k a pričítaj 1
    DEC b              // od b odčítaj 1
  }                    // koniec bloku asm
  printf("\na+b=%d a-b=%d",s,r);  // vypíš obsahy premenných
  printf("\na+1=%d b-1=%d",a,b);
}

Uvedený príklad ukazuje najjednoduchšie použitie inštrukcií ADD, SUB, INC, DEC. Všimnite si, že so zápismi adries premenných si nemusí programátor ani moc lámať hlavu. V tom mu totiž pomáha prekladač C++.

Násobenie

I keď programátori neradi používajú inštrukcie násobenia a delenia pre ich dlhú dobu prevádzania (na procesore 8086, u iných procesorov je už rýchle), ASM86 ich má. Niekedy dokonca neexistuje iná možnosť ako ich použiť. I tieto operácie sú definované len na celých číslach. Rozlišujeme tiež, či ich prevádzame so znamienkom, alebo bez znamienka. POZOR!, o koľkobitové násobenie sa jedná určuje označenie miesta zdroje.

Delenie

Táto operácia je jednou z najzdĺhavejších. Jej prevádzanie trvá (na 8086) až 190 periód hodín (sčítanie trvá okolo 3 periód). Jeho výhodou je ale to, že je možné zistiť ako výsledok po celočíselnom delení (DIV), tak i zvyšok po celočíselnom delení (MOD). A to všetko len jednou inštrukciou.
#include <stdio.h>
#include <conio.h>
unsigned char a,b,d,z;
unsigned int s;
main () {
  clrscr();
  printf("a=");
  scanf("%d",&a);
  printf("b=");
  scanf("%d",&b);
  asm {
    MOV AL, a   // do AL vlož hodnotu a
    MUL b       // vynásob hodnotou b (v pamäti)
    MOV s, AX   // do premennej s vlož súčin z registra AX
    MOV AH, 0   // nuluj AH (číslo je len 8 bitové)
    MOV AL, a   // do AL vlož hodnotu a
    DIV b       // vydeľ premennou b
    MOV d, AL   // výsledok vlož do premennej d
    MOV z, AH   // zbytok pt delení vlož do premennej z
  }
  printf("\na*b=%d",s);
  printf("\na div b=%d a mod b=%d",d,z);
}

Zmena počtu bitov

Často potrebujeme opraviť šestnásťbitové číslo na osembitové a naopak. Pri tejto zmene môže ale dôjsť k strate informácie v prípade úbytku bitov. Prevod čísiel bez znamienka prevedieme najjednoduchšie využitím pólenia registrov.

unsigned char b;
unsigned int w;
main() {
  b = 10;
  asm {
    MOV AL, b   // do AL osem bitov z premennej b
    MOV AH, 0   // nuluj AH
    MOV w, AX   // do premennej w vlož všetkých šestnásť bitov
  }
}

Práca s číslami v kódu BCD

Čísla v BCD kódu môžu byť uložené v týchto formátoch:




<= =>