Ľudmila Jánošíková | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Programovanie v jazyku symbolických adries | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
pre 32-bitové procesory Intel | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
BCD aritmetika
V tejto kapitole budeme hovoriť o inštrukciách, ktoré vykonávajú operácie s číslami uloženými v kóde BCD (Binary Coded Decimal). Táto forma reprezentácie čísiel slúži na spracovanie čísiel v desiatkovej sústave. S kódom BCD sa vyhneme starostiam s prevodom desiatkových čísiel na binárne pri vstupných dátach a nemusíme prevádzať binárne čísla na desiatkové pri výpise výsledkov z programu. BCD aritmetika je dôležitá aj z dôvodu zachovania presnosti čísla na všetkých významových miestach (čo je potrebné napr. v účtovníctve), ktorá by sa mohla porušiť zaokrúhľovaním zlomkovej časti čísla pri prevodoch medzi číselnými sústavami. V kóde BCD je každá číslica desiatkového čísla zobrazená v 4 bitoch ako dvojkové číslo. Rozoznávame zhustený a nezhustený formát BCD. V nezhustenom formáte je každá desiatková číslica uložená v jednom bajte (horné 4 bity sú nulové). V zhustenom formáte sú v jednom bajte uložené dve číslice. Ostatné detaily zobrazenia desiatkového čísla sa ponechávajú na programátora, hoci existujú určité konvencie, napr. 01h pred prvou číslicou znamená, že BCD číslo so znamienkom je kladné, zatiaľ čo 8h (80h v nezhustenom formáte) reprezentuje záporné číslo. Okrem toho býva zvykom vyhradiť pred zápisom čísla 1 bajt, ktorý obsahuje počet číslic BCD čísla. Napr. číslo -125 v zhustenom formáte BCD má tvar
Nezhustený BCD formát čísla 19 by mohol byť
Kvôli aritmetickým operáciám je tiež vhodné dodržať konvenciu uloženia čísiel v pamäti v obrátenom poradí slabík, t.j. v nezhustenom BCD formáte je najmenej významná číslica na najnižšej adrese a ďalšie číslice potom postupne na vyšších adresách. V zhustenom kóde BCD je najmenej významná dvojica číslic na najnižšej adrese, atď. Nevýhodou zobrazenia čísiel v BCD kóde je, že BCD reprezentácia je menej kompaktná ako binárna forma. Ďalšou nevýhodou je, že pri aritmetických operáciách s BCD číslami musíme vykonávať dodatočné úpravy, aby výsledok operácie bol správnym BCD číslom. Pri sčítaní dvoch čísiel v kóde BCD nastávajú problémy vtedy, keď dôjde k prenosu do vyššieho rádu desiatkového čísla. Pozrime sa, ako dopadne súčet 19+24 v zhustenom formáte BCD:
Problém je, že 1101 nepredstavuje v BCD kóde žiadnu číslicu. V 4 bitoch môžeme zakódovať 16 hodnôt, ale existuje len 10 desiatkových číslic. Ale ani v nasledujúcom príklade nedostaneme správny výsledok, hoci formát BCD zostane zachovaný:
V obidvoch prípadoch sa problém vyrieši, keď k dolným 4 bitom výsledku pripočítame 6:
resp.
Podobne treba urobiť aj korekciu v horných 4 bitoch pre druhú číslicu. Ako už naznačili uvedené príklady, korekciu robíme len v prípade, že došlo k pretečeniu zo štvorice bitov predstavujúcej desiatkovú číslicu, alebo je hodnota týchto bitov väčšia ako 9. Všetky uvedené testy a úpravy nemusíme robiť ručne, ale môžeme použiť inštrukciu
daa
(decimal adjust for addition)
Inštrukcia daa vykonáva korekciu výsledku sčítania dvoch čísiel v zhustenom formáte BCD v registri AL podľa nasledujúcich pravidiel:
V nasledujúcom príklade si ukážeme, ako by prebiehal súčet dvoch viacmiestnych BCD čísiel v zhustenom formáte. Pre jednoduchosť predpokladajme, že obidve čísla majú rovnaký počet číslic. ÚlohaSčítajte dve BCD čísla v zhustenom formáte uložené v dátovom segmente. Offset prvého čísla je v registri ESI, offset druhého čísla v EDI. V registri ECX je počet bajtov, ktoré čísla zaberajú. Čísla sú uložené v obrátenom poradí slabík. Výsledok uložte na miesto druhého sčítanca, teda od offsetu EDI. RiešenieČísla budeme sčítavať po bajtoch. Ku každému bajtu pripočítame prípadný prenos z predchádzajúceho rádu (použijeme inštrukciu adc) a po sčítaní vykonáme korekciu výsledku pomocou daa. Pretože na začiatku sčítania je prenos nulový, vynulujeme na začiatku programovej sekvencie príznakový bit CF.
clc ; CF := 0 Korekciu výsledku sčítania dvoch BCD čísiel v
nezhustenom formáte v registri AL vykonáva inštrukcia
aaa
(ASCII adjust for addition)
Ak obsah registra AL > 9 alebo AF = 1, pripočíta sa 0F6h k registru AX a príznaky AF a CF sa nastavia na 1. V opačnom prípade sa príznaky AF a CF vynulujú. ÚlohaSčítajte dve dvojmiestne čísla BCD v nezhustenom formáte uložené v registroch AX a BX a výsledok uložte do registra DX. RiešenieSúčet vypočítame v dvoch krokoch: najprv sčítame nižšie slabiky (AL a BL), pričom prenos sa pripočíta k obsahu registra AH. V druhom kroku sčítame vyššie slabiky (AH a BH). Pred korekciou výsledku vynulujeme register AH a prípadný prenos z vyššieho rádu potom zostane v AH.
add al,bl Korekciu výsledku odčítania dvoch BCD čísiel v
zhustenom formáte v registri AL vykonáva inštrukcia
das
(decimal adjust for subtraction)
podľa nasledujúcich pravidiel:
Korekciu výsledku odčítania dvoch BCD čísiel v zhustenom formáte v registri AL vykonáva inštrukcia aas (ASCII adjust for subtraction)
Ak obsah registra AL > 9 alebo AF = 1, odčíta sa 0F6h od registra AX a príznaky AF a CF sa nastavia na 1. V opačnom prípade sa príznaky AF a CF vynulujú. Operácie násobenia a delenia možno vykonávať len s BCD číslami v nezhustenom formáte. Inštrukcia aam (ASCII adjust for multiplication)
vykonáva korekciu výsledku násobenia dvoch BCD čísiel v nezhustenom formáte v registri AX. Číslo v registri AX upraví tak, aby významnejšia číslica výsledku bola v registri AH a menej významná číslica v AL. V nasledujúcom príklade ukážeme, ako možno násobiť viacmiestne BCD čísla. ÚlohaVynásobte BCD číslo uložené v obrátenom poradí slabík od adresy ESI jednomiestnym BCD číslom v registri DL. Obidve čísla sú v nezhustenom formáte. Počet číslic prvého čísla je v ECX. Výsledok uložte od adresy EDI. RiešenieSpomeňte si, ako násobíte jedným číslom ručne bez kalkulačky: vynásobíte jednu číslicu prvého čísla, pripočítate prenos z predchádzajúceho rádu, menej významnú číslicu zapíšete do výsledku a významnejšiu si zapamätáte ako prenos do ďalšieho rádu. V nasledujúcej ukážke programu si prenos do ďalšieho rádu zapamätáme v nasledujúcom bajte výsledku. Pretože na začiatku násobenia je prenos nulový, vynulujeme na začiatku programu prvý bajt výsledku. Po vynásobení jednej číslice prvého čísla obsahom registra DL vykonáme korekciu výsledku násobenia pomocou aam. Pripočítame prenos z predchádzajúceho rádu a urobíme korekciu po sčítaní. Až teraz je výsledok násobenia danej číslice (v registri AX) korektný. Obsah registra AL predstavuje číslicu výsledku, obsah AH prenos do vyššieho rádu.
mov byte ptr [edi],0 Operácia delenia v kóde BCD si vyžaduje úpravu
pred delením. Inštrukcia
aad
(ASCII adjust for division)
prevedie dve BCD číslice v nezhustenom formáte v registri AX na dvojkové číslo (vynásobí obsah AH desiatimi a pripočíta AL). Nasledujúca inštrukcia div potom nechá výsledok delenia v nezhustenom BCD formáte v registri AL a zvyšok po delení v nezhustenom BCD formáte v registri AH. ÚlohaVydeľte BCD číslo uložené v obrátenom poradí slabík od adresy ESI jednomiestnym BCD číslom v registri BL. Obidve čísla sú v nezhustenom formáte. Počet číslic prvého čísla je v ECX. Výsledok uložte od adresy EDI. RiešenieSpomeňte si, ako delíte viacmiestne čísla na papieri: zvyšok po delení v danom ráde sa prenáša do nasledujúceho rádu – stáva sa významnejšou číslicou delenca v nasledujúcom ráde. Pretože inštrukcia div ponechá zvyšok po delení v registri AH, stačí do AL skopírovať ďalšiu číslicu prvého čísla a máme v AX delenec v ďalšom ráde. Ten treba upraviť pomocou aad a môžeme deliť. Ešte si treba uvedomiť, že delenie začína od najvyššieho rádu, preto na začiatku programu musíme registre ESI a EDI upraviť tak, aby ukazovali na najvyšší bajt delenca, resp. výsledku.
add esi,ecx |
Načo je vám jazyk symbolických adries?
Architektúra moderných procesorov Služby operačného systému MS-DOS Služby operačného systému Windows 95/98/NT/XP |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Vydala Žilinská univerzita v Žiline, 2000. ISBN 80-7100-723-4. Otázky a pripomienky môžete poslať autorke. Naposledy upravené 19.10.2015. |