Kurs Assembleru - Zobrazování čísla v desítkové soustavě

Raster/c.p.u., 2005

V dnešním díle nepravidelného kursu programování v Assembleru se podíváme na problematiku zobrazování hexadecimálního čísla v desítkovém tvaru. Řekněme tedy, že ve svém programu používáte dvoubytové číslo (tj. $0000-$FFFF), které chcete zobrazit na obrazovce v desítkové soustavě (tj. 00000-65535).

Předvedeme si dva odlišné principy, kterými lze toto řešit.

1. Způsob pomocí dělení 10

---------------------------

Číslo opakovaně dělíme hodnotou 10. Zbytek po dělení vždy použijeme jako jednu výslednou cifru pro zobrazení, přičemž výstup je sestavován pozpátku od poslední cifry po první (tj. od jednotek po desetitisíce).

Příklad: Mějme číslo $4321
1. $4321 / 10 = $06B6 zbytek 5
2. $06B6 / 10 = $00AB zbytek 8
3. $00AB / 10 = $0011 zbytek 1
4. $0011 / 10 = $0001 zbytek 7
5. $0001 / 10 = $0000 zbytek 1
Výsledná zobrazená hodnota je tedy 17185.

Jak je z příkladu vidět, poslední (páté) dělení je již zbytečné, neboť výsledek dělení ve čtvrtém kroku již můžeme rovnou použít jako cifru desetitisíců.

Tento princip včetně zmíněné jednoduché optimalizace vynecháním pátého dělení je demonstrován v ukázce SHOW10A. Volá se podprogram "zobraz", jenž vždy zobrazí hodnotu obsaženou na paměťových buňkách "zobraz_db" a "zobraz_hb". Toto se provádí v cyklu od $0000 až po $FFFF, tj. zobrazovány jsou hodnoty od 00000 po 65535. Na závěr se pak vypíše celková doba běhu programu v padesátinách sekundy.

2. Způsob pomocí odečítání mocnin 10

-------------------------------------

Od čísla odečítáme mocniny deseti a započítáváme vždy počet těchto odečtení dokud bude výsledek nezáporný. V případě záporného výsledku se vrátíme k poslední nezáporné hodnotě a posuneme se na výpočet další cifry. Začneme hodnotou 10000, pak 1000, 100, 10 a 1. Výsledek tedy bude sestavován z počtů odečtení, a v pořadí od první cifry po poslední (tj. od desetitisíců po jednotky).

Příklad: Mějme číslo $4321
1. $4321 - 10000 = $1C11 (1.odečtení)
   $1C11 - 10000 = záporný výsledek
2. $1C11 - 1000 = $1829 (1.odečetní)
   $1829 - 1000 = $1441 (2.odečtení)
   $1441 - 1000 = $1059 (3.odečtení)
   $1059 - 1000 = $0C71 (4.odečtení)
   $0C71 - 1000 = $0889 (5.odečtení)
   $0889 - 1000 = $04A1 (6.odečtení)
   $04A1 - 1000 = $00B9 (7.odečtení)
   $00B9 - 1000 = záporný výsledek
3. $00B9 - 100 = $0055 (1.odečtení)
   $0055 - 100 = záporný výsledek
4. $0055 - 10 = $004B (1.odečtení)
   $004B - 10 = $0041 (2.odečtení)
   $0041 - 10 = $0037 (3.odečtení)
   $0037 - 10 = $002D (4.odečtení)
   $002D - 10 = $0023 (5.odečtení)
   $0023 - 10 = $0019 (6.odečtení)
   $0019 - 10 = $000F (7.odečtení)
   $000F - 10 = $0005 (8.odečtení)
   $0005 - 10 = záporný výsledek
5. $0005 - 1 = $0004 (1.odečtení)
   $0004 - 1 = $0003 (2.odečtení)
   $0003 - 1 = $0002 (3.odečtení)
   $0002 - 1 = $0001 (4.odečtení)
   $0001 - 1 = $0000 (5.odečtení)
   $0000 - 1 = záporný výsledek
Výsledná zobrazená hodnota je tedy 17185.

Můžeme provést jednoduchou optimalizaci pro čtvrtý a pátý průběh, vycházející z úvahy, že po třetím průběhu je už výsledná hodnota vždy menší než 100, a odečítání tedy již stačí provádět pouze pro jednobyteovou hodnotu. Závěrečný pátý průběh pak lze vynechat zcela a použít pro cifru jednotek přímo poslední nezápornou hodnotu ze čtvrtého průběhu.

Tento princip včetně zmíněné jednoduché optimalizace čtvrtého průběhu a s vynecháním pátého průběhu je demonstrován v ukázce SHOW10B. Volá se podprogram "zobraz", jenž vždy zobrazí hodnotu obsaženou na paměťových buňkách "zobraz_db" a "zobraz_hb". Toto se provádí v cyklu od $0000 až po $FFFF, tj. zobrazovány jsou hodnoty od 00000 po 65535. Na závěr se pak vypíše celková doba běhu programu v padesátinách sekundy.

Porovnání rychlosti obou způsobů:

(hodnota za dvojtečkou znamená dobu - čím větší tím horší)

SHOW10A:
čísla 00000-65535:  4476
65536x číslo 00000: 4222
65536x číslo 59999: 4607

SHOW10B:
čísla 00000-65535:  1710
65536x číslo 00000:  550
65536x číslo 59999: 2842

Operace dělení je náročnější na výpočetní výkon, takže první způsob je pomalejší. Zobrazení různých hodnot však trvá vždy zhruba stejnou dobu - rozdíl cca do 10%.

Druhý způsob je vždy rychlejší, a to ještě velmi závisí na zobrazované hodnotě. Mezi nejhorší zobrazovanou hodnotou 59999, kdy musí odečítací metoda provést největší počet cyklů, a nejlepší zobrazovanou hodnotou 00000 s minimálním celkovým počtem odečítacích cyklů, je rozdíl potřebné doby více než pětinásobný.

Poznámka: U výkonnostně náročných her a programů, kde by neustálé převádění hexa čísel do desítkového tvaru kvůli zobrazování stálo příliš mnoho času, se většinou používá BCD reprezentace a decimal modus, ale o tom kdyžtak někdy příště.