Ľudmila Jánošíková

Programovanie v jazyku symbolických adries

pre 32-bitové procesory Intel
Obsah Index
Aritmetické inštrukcie

add register/pamäť, register/pamäť/číslo (add)

OF SF ZF AF PF CF
* * * * * *

Inštrukcia add sčíta obidva operandy a výsledok uloží do ľavého operandu.

sub register/pamäť, register/pamäť/číslo (subtract)

OF SF ZF AF PF CF
* * * * * *

Inštrukcia sub odčíta pravý operand od ľavého operandu a výsledok uloží do ľavého operandu.

adc register/pamäť, register/pamäť/číslo (add with carry)

OF SF ZF AF PF CF
* * * * * *

Inštrukcia adc sčíta obidva operandy a hodnotu príznakového bitu CF a výsledok uloží do ľavého operandu. Táto inštrukcia sa používa pri sčítaní celých čísiel dlhších než veľkosť univerzálneho registra v danom režime procesora. Vo virtuálnom režime sú univerzálne registre 32-bitové, preto nemôžeme v jednej operácii sčítať dve čísla väčšieho rozsahu. Ak je číslo uložené napr. v štyroch slovách (64 bitov), musíme operáciu sčítania vykonať v dvoch krokoch: najprv sčítať nižšie dvojslovo (32 bitov) operandov a potom sčítať vyššie dvojslovo aj s prípadným prenosom (ako keď na papieri sčítavate viacmiestne čísla od najnižšieho rádu).

Príklad: Sčítajte premenné A a B typu qword a výsledok uložte do premennej C.

A DQ 0FFFFFFFFh
B DQ 9
C DQ ?

.386
mov eax,dword ptr A
add eax,dword ptr B
mov dword ptr C,eax
mov eax,dword ptr A+4
adc eax,dword ptr B+4
mov dword ptr C+4,eax

Upozorňujeme, že medzi add a adc sa nesmie vyskytnúť inštrukcia, ktorá by zmenila hodnotu príznaku CF. Výsledok sčítania by nebol korektný.

sbb register/pamäť, register/pamäť/číslo (subtract with borrow)

OF SF ZF AF PF CF
* * * * * *

Inštrukcia sbb odčíta pravý operand a príznak CF od ľavého operandu a výsledok uloží do ľavého operandu. Používa sa pri odčítaní čísiel väčšieho rozsahu, ktoré sa nezmestia do univerzálnych registrov.

inc register/pamäť (increment)

OF SF ZF AF PF CF
* * * * * -

Inštrukcia inc zvýši hodnotu operandu o 1. Môžeme to samozrejme urobiť aj pomocou inštrukcie add, ale inc je rýchlejšia a stručnejšia (napr. inc bx sa preloží do 1 bajtu, ale add bx,1 do 3 bajtov). Všimnite si, že inštrukcia inc (na rozdiel od add) nemení príznak CF!

dec register/pamäť (decrement)

OF SF ZF AF PF CF
* * * * * -

Inštrukcia dec zníži hodnotu operandu o 1.

cmp register/pamäť, register/pamäť/číslo (compare)

OF SF ZF AF PF CF
* * * * * *

Inštrukcia cmp porovná operandy tak, že pravý odčíta od ľavého, nastaví príznakové bity podľa výsledku operácie, ale samotný výsledok nikam neuloží.

mul register/pamäť (unsigned multiply)

OF SF ZF AF PF CF
* ? ? ? ? *

Na rozdiel od operácií sčítania a odčítania, ktoré majú rovnaké inštrukcie pre operandy bez znamienka aj operandy so znamienkom, pri násobení a delení musíme rozlíšiť, s akými číslami pracujeme. Ak chceme násobiť čísla bez znamienka, použijeme inštrukciu mul, ktorá vynásobí operand obsahom akumulátora. Akumulátorom je register AL, AX alebo EAX podľa toho, aký je typ operandu. Podľa typu operandu sa tiež určí register, do ktorého sa uloží výsledok. Môžu nastať tieto prípady:

  1. operand je typu byte – násobí sa obsahom registra AL, výsledok sa uloží do AX;
  2. operand je typu word – násobí sa obsahom registra AX, výsledok sa uloží do dvojice registrov DX:AX;
  3. operand je typu dword – násobí sa obsahom registra EAX, výsledok sa uloží do dvojice registrov EDX:EAX.

Príznakové bity OF a CF sa nastavia na 1, ak výsledok presiahne rozsah operandov, t.j. ak je väčší ako bajt, resp. slovo alebo dvojslovo. V opačnom prípade sa OF a CF vynulujú. Treba pamätať na to, že horná polovica výsledku sa zmení aj v prípade, keď výsledok nepresiahne rozsah operandov (registre AH, resp. DX alebo EDX sa vynulujú)!

Z hľadiska rýchlosti je pri násobení 32-bitových registrov konštantami 2, 3, 4, 5, 8, 9 výhodnejšie používať namiesto inštrukcie mul inštrukciu lea, napr.

lea eax,[eax+eax*2]; eax := 3*eax

imul register/pamäť

imul register, register/pamäť/číslo

imul register, register/pamäť, číslo

(signed multiply)

OF SF ZF AF PF CF
* ? ? ? ? *

Inštrukcia imul vykonáva násobenie hodnôt so znamienkom. Ako vidíte, možnosti násobenia sa rozšírili o násobenie konštantou a o voľbu druhého operandu, v treťom prípade aj výsledku. Prvý tvar inštrukcie imul zodpovedá inštrukcii mul. V druhom prípade sa ľavý operand vynásobí pravým a výsledok sa uloží do ľavého operandu; obidva operandy musia mať rovnaký typ (word alebo dword), napr.:

imul dx,word ptr [di]

V treťom prípade sa navzájom vynásobia druhý a tretí operand zľava a výsledok sa uloží do prvého operandu zľava; opäť operandy musia mať rovnaký typ (word alebo dword).

Príznakové bity OF a CF sa nastavia na 0, ak horná polovica výsledku je znamienkovým rozšírením dolnej polovice; v opačnom prípade sa nastavia na 1.

div register/pamäť (unsigned divide)

OF SF ZF AF PF CF
? ? ? ? ? ?

Inštrukcia div vykonáva celočíselné delenie čísiel bez znamienka. Operand inštrukcie sa považuje za deliteľ. Delenec a registre, do ktorých sa ukladá podiel a zvyšok po delení, sú implicitné a závisia od typu operandu – pozri tab. 5.

Príklad:

mov ax,51
mov dl,10

div dl ; al ¬ 5, ah ¬ 1

Ak delíme nulou, alebo ak sa podiel nezmestí do určeného registra, generuje sa prerušenie číslo 0.

Tabuľka 5
Implicitné operandy operácie delenia
Delenec Deliteľ Podiel Zvyšok
AX 8-bitový register alebo pamäťový operand AL AH
DX:AX 16-bitový register alebo pamäťový operand AX DX
EDX:EAX 32-bitový register alebo pamäťový operand EAX EDX

idiv register/pamäť (signed divide)

OF SF ZF AF PF CF
? ? ? ? ? ?

Inštrukcia idiv vykonáva celočíselné delenie čísiel so znamienkom. Implicitné operandy inštrukcie sa určujú podľa tab. 5.

Ako sme videli, pri delení musí byť delenec uložený v registroch, ktoré majú dvojnásobnú veľkosť než deliteľ. Ak má delenec rovnaký typ ako deliteľ, uložíme ho do dolného registra a horný register vynulujeme, napr. ak chceme obsah registra BH vydeliť obsahom registra BL, musíme vykonať nasledujúce príkazy:

mov al,bh
mov ah,0
div bl

Takto to funguje pri delení čísiel bez znamienka. Pri delení so znamienkom musíme vykonať znamienkové rozšírenie dolnej polovice delenca do hornej polovice. Znamienkové rozšírenie majú na starosti 4 inštrukcie:

cbw (convert byte to word)

OF SF ZF AF PF CF
- - - - - -

Inštrukcia cbw konvertuje 8-bitovú hodnotu so znamienkom v registri AL na 16-bitovú hodnotu so znamienkom. Výsledok sa uloží do registra AX. Konverzia prebehne tak, že všetky bity registra AH sa naplnia najvyšším bitom registra AL. Napr. ak chceme číslo -15 ( = 0F1h) uložené v registri BH vydeliť číslom 2 v registra BL, vykonáme nasledujúce príkazy:

mov al,bh
cbw; ax := FFF1h = -15
idiv bl; al := F9h = -7, ah := FFh = -1

cwd (convert word to doubleword)

OF SF ZF AF PF CF
- - - - - -

Inštrukcia cwd konvertuje 16-bitovú hodnotu so znamienkom v registri AX na 32-bitovú hodnotu so znamienkom. Výsledok sa uloží do dvojice registrov DX:AX. Všetky bity registra DX sa naplnia najvyšším bitom registra AX.

cwde (convert word to doubleword extended)

OF SF ZF AF PF CF
- - - - - -

Inštrukcia cwde konvertuje 16-bitovú hodnotu so znamienkom v registri AX na 32-bitovú hodnotu so znamienkom v registri EAX.

cdq (convert doubleword to quadword)

OF SF ZF AF PF CF
- - - - - -

Inštrukcia cdq konvertuje 32-bitovú hodnotu so znamienkom v registri EAX na 64-bitovú hodnotu so znamienkom v dvojici registrov EDX:EAX.

Ako poslednú zahrnieme do skupiny aritmetických inštrukcií inštrukciu

neg register/pamäť (two's complement negation)

OF SF ZF AF PF CF
* * * * * *

Inštrukcia neg zmení znamienko operandu (nahradí operand jeho dvojkovým doplnkom). Príznak CF sa nastaví na 0, ak má operandu nulovú hodnotu, inak sa nastaví na 1. Príklad:

mov al,-15 ; al := -15 = 11110001b
neg al     
; al := 15 = 00001111b
mov bl,al 
; bl := 15
neg bl     ; bl := -15

Hore

Načo je vám jazyk symbolických adries?

Architektúra moderných procesorov

Registre

Spôsoby adresovania

Premenné a návestia

Symbolické konštanty

Inštrukčný súbor

Segmentové direktívy

Moduly

Služby operačného systému MS-DOS

Služby operačného systému Windows 95/98/NT/XP

Systémová úroveň vstupu a výstupu

Prostriedky pre prípravu programu

Inštrukcie pre presun údajov | Logické inštrukcie
Vydala Žilinská univerzita v Žiline, 2000. ISBN 80-7100-723-4.
Otázky a pripomienky môžete poslať autorke.
Naposledy upravené 28.9.2015.