Numeros BCD

Los números BCD se ven representados de manera natural, tal y como nosotros los veríamos; el 99 hexadecimal, representa al 99 decimal.

Para conseguir esto, un byte puede representar números del 0 al 99, dividiendo el byte en dos nibbles (4 bits). Cada nibble puede representar números del 0 a 9.

De esta manera, el 10 hexadecimal, que en decimal es 16, en BCD representa el 10 decimal. Dicho de otra manera, vemos los números hexadecimales como si de números decimales se tratara.

Para representar un número de 10 dígitos, se necesitan 5 bytes. Se puede usar un byte extra para indicar la posición de la coma, y así poder trabajar con decimales. Los números BCD se usan para operar con cifras de más de 16 bits.

A la hora de operar con números BCD, hay que tener muy presente la instrucción DAA (Decimal Adjust Accumulator). DAA realiza ajustes en los resultados de operaciones con números BCD, y funciona de la siguiente manera:

  • Comprueba los bits 0, 1, 2 y 3. Si contienen un dígito no BCD (mayor de 9) o se establece el flag H; suma o resta, dependiendo de la operación, 06h (0000 0110b) al byte.
  • Comprueba los bits 4, 5, 6 y 7. Si contienen un dígito no BCD (mayor de 9) o se establece el flag C; suma o resta, dependiendo de la operación, 60h (0110 0000b) al byte.

De esta manera, si tenemos $09 y sumamos $01, el resultado es $0A. Tras ejecutar DAA, el resultado es $10. Después de cada instrucción aritmética, incremento o decremento hay que ejecutar DAA.

ld a, $09     ; A = $09
inc a ; A = $0A
daa ; A = $10

dec a ; A = $0F
daa ; A = $09

add a, $03 ; A = $0C
daa ; A = $12

sub $03 ; A = $0F
daa ; A = $09

Por otro lado, la manera de obtener el código ASCII de cada nibble, es relativamente sencilla.

La rutina que se muestra a continuación, recibe un número BCD en el registro B y lo muestra en pantalla.

; -----------------------------------------------------
; Imprime en pantalla un número BCD.
; Entrada: B -> Número BCD a imprimir.
; Altera el valor del registro AF.
; -----------------------------------------------------
PrintBCD:
ld a, b ; Carga en A el número a imprimir
and $f0 ; Se queda con el nibble superior
rrca
rrca
rrca
rrca ; Lo rota cuatro veces para pasarlo al nibble inferior
add a, '0' ; Suma el ASCII del 0 para obtener el ASCII del número
rst $10 ; Muestra el número en pantalla (Spectrum)
;call $bb5a ; Muestra el número en pantalla (Amstrad CPC)

ld a, b ; Vuelve a cargar el número a imprimir en A
and $0f ; Se queda con el nibble inferior
add a, '0' ; Suma el ASCII del 0 para obtener el ASCII del número
rst $10 ; Muestra el número en pantalla (Spectrum)
;call $bb5a ; Muestra el número en pantalla (Amstrad CPC)

ret ; Sale de la rutina

RST $10, en ZX Spectrum, imprime en pantalla el carácter correspondiente al código Ascii cargado en el registro A.

CALL $bb5a, hace lo propio en Amstrad CPC.