NOVINKA! E-learningové kurzy umělé inteligence. Nyní AI za nejlepší ceny. Zjisti více:
NOVINKA – Víkendový online kurz Software tester, který tě posune dál. Zjisti, jak na to!

Lekce 11 - Assembler - Kombinace skoků a příznaky

V minulé lekci, Assembler - Podmíněné a nepodmíněné skoky, jsme si řekli něco o nepodmíněných a podmíněných skocích, pomocí kterých můžeme vytvořit podmínky a cykly známé z vyšších jazyků.

V dnešním ASM tutoriálu se naučíme kombinovat podmíněné a nepodmíněné skoky, zjistíme, jak skokové instrukce získají výsledek z CMP a jak porovnávat signed čísla.

Příklad - Podmíněné a nepodmíněné skoky dohromady

Říkali jsme si, že můžeme podmíněné a nepodmíněné skoky snadno kombinovat. Ukažme si tedy na příkladu, jak se používají dohromady:

zacatek:
mov cx, 5

.znovu:
mov si, message
call print_string

dec cx

cmp cx, 0
jz .return
jmp .znovu

.return:
mov si, konec
call print_string
ret

print_string:
lodsb
cmp al, 0
jz .return
mov ah, 0eh
mov bx, 7h
int 10h
jmp print_string

.return:
ret

message db 'CX != 0', 13, 10, 0
konec db 'CX == 0', 0

Z kódy byste již měli vyčíst, že vypisuje text 5x, tedy dokud není CX rovno 0. Vyzkoušeli jsme si tak i instrukci DEC ke snížení hodnoty a vlastně jsme si napsali instrukci loop.

Všimněte si použití funkce print_string, kterou jsem již používali, jako příkladu. A také. že pokud dáme před návěstí ., stane se z něj "pod-návěstí" a nemusíme tak používat očíslování apod. (Platí pro NASM).

Příznaky

Již víme, že CMP vykoná operaci A - B a na její výsledek pak pomocí dalších instrukcí reagujeme. Jak ale tyto instrukce vědí, jaký výsledek byl? CMP totiž podle výsledku porovnání nastaví tzv. flagy (příznaky) a následující skákací instrukce reagují na hodnoty uložené v těchto příznacích.

Pokud znáte principy počítačů, víte, že odčítání se vnitřně provádí jako přičtení dvojkového doplňku druhého čísla.

Flagy nastavuje kromě CMP i několik dalších instrukcí a nemusí nastavit všechny, ale jen některé z nich. Nejsou tedy jen záležitost porovnávání, ale i několika dalších instrukcí, např. i těch aritmetických.

Flagy mohou být vždy buď 1 nebo 0. V registru EFLAGS je velké množství flagů, ale v podmíněných skocích se používají jen tyto flagy:

  • ZF - Zero flag - Nastaví se, pokud je výsledek 0.
  • SF - Sign flag - Nastaví se, pokud je nejvyšší bit výsledku operace 1 (MSB jako Most Significant Bit, obvykle ten nejvíce vlevo). Název pochází od toho, že pokud je číslo uložené jako signed, tak tento bit v čísle označuje, zda je číslo záporné či nikoli.
  • CF - Carry flag - Nastaví se, pokud při operaci došlo k přetečení (např. přičteme 1 k 255 v proměnné o velikosti 1 bajt). Výsledek bude tedy 0, ale zapne se flag Carry. Pokud máme signed číslo, tak tam se o přetečení dozvíme z flagu overflow níže.
  • OF - Overflow flag - Nastaví se, pokud dojde k přetečení hodnoty signed čísla (pro tento typ čísel nelze k ověření přetečení použít Carry flag).
  • PF - Parity flag - Flag parity se nastaví, pokud je v nejnižším bajtu výsledku sudý počet jedničkových bitů.

Tabulka skoků včetně příznaků a porovnávání signed čísel

Jelikož již známe flagy, můžeme si uvést další, kompletnější tabulku skoků a uvést do ní na jaký flag nastavený pomocí CMP daná skoková instrukce reaguje. Také si přidáme instrukce pro práci se signed čísly. Takových tabulek nás čeká ještě spoustu, ASM je hodně o tabulkách instrukcí :)

Instrukce Porovnání Popis Typ čísel Flagy
JO (Jump if Overflow)   Skočí, pokud došlo k přetečení   OF == 1
JNO (Jump if Not Overflow)   Skočí, pokud nedošlo k přetečení   OF == 0
JS (Jump if Sign)   Skočí, pokud byl nastaven sign bit   SF == 1
JNS (Jump if Not Sign)   Skočí, pokud nebyl nastaven sign bit   SF == 0
JE (Jump if Equal)
JZ (Jump if Zero)
A == B Skočí, pokud byly hodnoty rovné
Skočí, pokud byl rozdíl hodnot 0
  ZF == 1
JNE (Jump if Not Equal)
JNZ (Jump if Not Zero)
A != B Skočí, pokud nebyly hodnoty rovné
Skočí, pokud nebyl rozdíl hodnot 0
  ZF == 0
JB (Jump if Below)
JNAE (Jump if Not Above or Equal)
JC (Jump if Carry)
A < B Skočí, pokud byl rozdíl hodnot záporný
Skočí, pokud byla hodnota menší
Skočí, pokud byl nastaven flag carry
unsigned CF == 1
JNB (Jump if Not Below)
JAE (Jump if Above or Equal)
JNC (Jump if Not Carry)
A >= B Skočí, pokud nebyla hodnota menší
Skočí, pokud nebyl rozdíl hodnot větší nebo roven 0
Skočí, pokud nebyl nastaven flag carry
unsigned CF == 0
JBE (Jump if Below or Equal)
JNA (Jump if Not Above)
A <= B Skočí, pokud byla hodnota menší nebo rovná
Skočí, pokud byl rozdíl hodnot menší nebo roven 0
unsigned CF == 1 nebo ZF == 1
JA (Jump if Above)
JNBE (Jump if Not Below or Equal)
A > B Skočí, pokud byla hodnota větší
Skočí, pokud byl rozdíl hodnot větší nebo roven 0
unsigned CF == 0 a ZF == 0
JL (Jump if Less)
JNGE (Jump if Not Greater or Equal)
A < B Skočí, pokud byla hodnota menší
Skočí, pokud hodnota nebyla větší nebo rovna
signed SF != OF
JGE (Jump if Greater or Equal)
JNL (Jump if Not Less)
A >= B Skočí, pokud byla hodnota větší nebo rovna
Skočí, pokud hodnota nebyla menší
signed SF == OF
JLE (Jump if Less or Equal)
JNG (Jump if Not Greater)
A <= B Skočí, pokud byla hodnota menší nebo rovná
Skočí, pokud hodnota nebyla větší
signed ZF == 1 nebo SF != OF
JG (Jump if Greater)
JNLE (Jump if Not Less or Equal)
A > B Skočí, pokud byla hodnota větší
Skočí, pokud hodnota nebyla menší nebo rovná
signed ZF == 0 a SF == OF
JP (Jump if Parity)
JPE (Jump if Parity Even)
  Skočí, pokud byl nastaven parity bit
Skočí, pokud byla sudá parita
  PF == 1
JNP (Jump if Not Parity)
JPO (Jump if Parity Odd)
  Skočí, pokud nebyl nastaven parity bit
Skočí, pokud byla lichá parita
  PF == 0

Tato tabulka je stále zjednodušená a neobsahuje instrukce pro všechny podmíněné skoky, například ty podle obsahu registrů. Nám však takto bohatě stačí :)

Některé uvedené skoky podle příznaků se nepoužívají tak často. My je budeme používat např. k tomu, abychom věděli, jestli se nějaká operace zdařila, či nikoliv.

V příští lekci, Assembler - Signed a Unsigned čísla, budeme pracovat s celými čísly se znaménkem.


 

Předchozí článek
Assembler - Podmíněné a nepodmíněné skoky
Všechny články v sekci
Základy assembleru
Přeskočit článek
(nedoporučujeme)
Assembler - Signed a Unsigned čísla
Článek pro vás napsal Jakub Verner
Avatar
Uživatelské hodnocení:
3 hlasů
Autor se věnuje programování v x86 Assembleru.
Aktivity