Převod binární hodnoty na formát BCD

Další z řady řešených elementárních úloh je převod binární hodnoty na formát BCD, kde každá cifra v rozsahu 0..9 je (poněkud neúsporně) uložena ve čtyřech za sebou jdoucích bitech. Do jednoho osmibitového registru se pak vejdou takovéto BCD cifry dvě.

A aby to bylo úplně jasné, uvedu příklad. Mám ve zvoleném registru hodnotu C0h a chci ji vytisknout jako „lidské“ číslo. Ideálně očekávám výsledek 192. Takže naplním registr hodnotou C0h, zavolám proceduru pro převod BIN>BCD a například v registrovém páru D:E se mi vrátí hodnota 0000 0001 1001 0010 (binárně). Což jsou ve správném pořadí BCD cifry 0192. Zbývá jen tyto cifry vytisknout, či si je někde uložit. Ale to už je jiná úloha.

Následující vzorové procedury jsou sice určeny pro procesor i8080, nicméně asi každý procesor obsahuje instrukci pro dekadickou korekci, na i8080 nazvanou DAA (instrukční kód 27h). Pokud by ji použitý procesor neobsahoval, lze si napsat dílčí proceduru dle funkčního popisu instrukce DAA:

  1. Je-li hodnota 4 nejnižších bitů registru větší než 9, nebo je nastaven příznak AC z předchozího kroku, připočte se k registru číslo 6 (korekce nižší BCD cifry).
  2. Pokud je nyní hodnota 4 nejvyšších bitů registru větší než 9, nebo je nastaven příznak CY z předchozího kroku, připočte se k registru číslo 60h (korekce vyšší BCD cifry).

Speciální případ bílého trpaslíka pro jednoduchý převod osmibitové binární hodnoty v rozsahu 00..99 na procesoru rodiny i8051je instrukce DIV AB. Stačí do registru A načíst převáděné binární číslo, do registru B načtu hodnotu 10 (desítkově) a po provedení instrukce DIV AB mám v registru A počet desítek a v registru B počet jednotek BCD čísla. Obojí zaručeně v rozsahu 0..9.

Všech pět uvedených demonstračních procedur využívá sekvence instrukcí DAD H/ADC A. Pokud tuto sekvenci zopakuji osmkrát, přesunu číslo z registru H do registru A. Pokud za každým krokem provedu instrukci DAA, budu postupně převádět váhy původního, šestnáctkového, čísla 80h-40h-20h-10h-08h-04h-02h-01h na dekadické ekvivalenty 128-64-32-16-8-4-2-1. V tomto zjednodušeném příkladu ovšem mohu takto převádět čísla v rozsahu 00..99, neboť třetí cifra řádu stovek se již do „dvoumístného“ registru A nevejde. Ale princip funguje takto.

Jak jsem již napsal, procedur je pět. Dvě pro šestnáctibitové vstupní binární číslo a dvě pro osmibitové vstupní číslo. Ta pátá „b7bcdf“ je pak „rychlostní“ variantou „b7bcd“ pro případ, že nemáte moc strojového času k dispozici a využíváte jen omezený vstupní rozsah hodnot, zde 00..99. Vynechání cyklu FOR/NEXT přinese zkrácení doby vykonávání procedury na 55% původní hodnoty. A to už stojí za to. Obecně lze použít jen tu nejuniverzálnější proceduru (b16bcd) ale v praxi je to vždy kompromis mezi rychlostí (počtem taktů) a tím, co procedura umí (jak je univerzální).

 

 

 

 

Délka 19 bajtů u procedur „b8bcd“ a „b15bcd“ není náhodná. Jsou to identické procedury, jen s odlišným počtem převáděných bitů (buď osm nebo šestnáct).

Vzorový program s procedurami pro převod binárních čísel na formát BCD

2 komentáře u „Převod binární hodnoty na formát BCD

  1. RomBor

    Ešte by som doplnil, že v b7bcd môžeme ušetriť jednu iteráciu a v b15bcd dokonca dve iterácie tým, že pred cyklom dáme jednu/dve rotácie DAD H naviac. Vzhľadom na to, že vstupný parameter v H, resp. v HL bude mať vždy 7., resp. 7. a 6. bit nulový, tak vnútorné operácie cyklu nie sú potrebné (výsledok nezmenia). Predĺži to rutinu o 1 resp. 2 byty, ale ušetrí čas.

    b7bcd:  mvi b,7         ; 8-bitové číslo (ale stačí 7 iterací)
            xra a           ; příprava akumulátoru výsledku
            dad h           ; první posun H vlevo, MSB je vždy 0
    cykl7:  dad h           ; posun H vlevo, CY = H[7]
            adc a           ; A := 2 x A + CY
            daa             ; dekadická korekce
            dcr b
            jnz cykl7       ; NEXT bit
            ret
    
    b15bcd: mvi b,14        ; převádím 16-bitové číslo (stačí 14 iterací)
            lxi d,0         ; příprava akumulátoru výsledku
            dad h           ; první dva posuny HL vlevo (2MSB jsou vždy nulové)
            dad h
    cykl15: dad h           ; posun HL vlevo, CY = H[7]
            mov a,e         ; DE := 2 x DE + CY
            adc a
            daa             ; (včetně dekadické korekce)
            mov e,a
            mov a,d
            adc a
            daa
            mov d,a
            dcr b
            jnz cykl15      ; NEXT bit
            ret
    
    1. Libor L.A.

      Máš samozřejmě pravdu. Toho jsem si nevšiml.

      V tomto případě však nebudu upravovat procedury v hlavním článku, nechám je tak, jak tam jsou. Z „pedagogického“ hlediska bude mít větší cenu, když případný zájemce bude mít možnost porovnat původní proceduru s její vylepšenou verzí.

      Díky za připomínku.

Napsat komentář: RomBor Zrušit odpověď na komentář

Vaše e-mailová adresa nebude zveřejněna.