Hola.
He escrito una posible solución, pero, desde luego, no es la única.
El problema que se plantea es transformar un valor grande en binario a un valor decimal, colocando cada cifra en un byte.
Supuestos
- El valor del que partimos es un "largo" (4 bytes). Al estar en un 6502 se guarda en memoria en el orden little-endian (primero los bytes bajos).
- En ese caso el mayor número que se puede representar en decimal es 2³²-1 = 4 294 967 295. O sea, 10 dígitos.
- El resultado se almacenará como big-endian (primero los valores más significativos).
Solución
- Se utilizará el método de ir sumando en un espacio llamado parcial las sumas parciales de un valor llamado multiplicador, por cada bit que esté puesto en el valor inicial.
- Tanto parcial como multiplicador se almacenarán en 5 bytes, en formato BCD.
- Al principio, multiplicador se establecerá en $0000000001 y se irá multiplicando por 2 por cada bit que probemos en valor.
- Es decir, vamos sumando las potencias de 2 correspondientes a los bit puestos en valor.
- Después de hacer todas las sumas, recorremos parcial y transformamos la codificación BCD en bytes separados en resultado.
Se podría optimizar y unificar los espacios de
parcial y
resultado, pero eso se deja como ejercicio para el lector (realmente, es muy fácil).
Implementación
- Se usa el ensamblador y emulador de 6502 virtual en https://www.mdawson.net/asm6502/6502asm.php
- Se puede copiar el código allí, pulsar el botón Compile, el botón Execute, y vemos el resultado en la pestaña Memory Dump. El programa se encuentra a partir de la dirección $1000 y el resultado empieza en $10a0.
No lo he probado con muchos números, pero hasta ahora ha funcionado bien.
Código: Seleccionar todo
; *** Vector de reset _siempre_ debe estar puesto ***
org $FFFC
dcw start
; Inicio de programa
org $1000
start:
ldy #$00 ; índice dentro de valor
; bucle por los bytes de valor
loop:
lda #$01 ; iniciar máscara
sta mascara
; bucle por los 8 bits de cada byte
loop1:
lda mascara
and valor,y ; aquí está la clave: solo hacemos la suma si el bit está puesto a 1
beq siguiente_bit
; hacer la suma
ldx #$4
clc ; sin acarreo al principio
sed ; sumamos en BCD
loop_x1:
lda multiplicador,x
adc parcial,x ; el flag C va llevando el acarreo
sta parcial,x
dex
bpl loop_x1
cld
siguiente_bit:
; multiplicar por 2 el multiplicador
ldx #$4
clc ; sin acarreo al principio
sed ; multiplicamos por 2 en BCD
loop_x2:
lda multiplicador,x
adc multiplicador,x ; el flag C va llevando el acarreo
sta multiplicador,x
dex
bpl loop_x2
cld
; siguiente mascara
asl mascara
bcc loop1
siguiente_byte:
iny
cpy #4
bne loop
; hacer la conversión de BCD a bytes sueltos
ldx #$04
ldy #$09
loop_res:
lda parcial,x
and #$0F ; primer BCD
sta resultado,y
dey
lda parcial,x
and #$F0 ; segundo BCD
lsr
lsr
lsr
lsr
sta resultado,y
dey
dex
bpl loop_res
; FIN
brk
org $1060
mascara:
dcb $00
org $1070
valor:
dcl $642664
org $1080
multiplicador:
dcb $00, $00, $00, $00, $01
org $1090
parcial:
dcb $00, $00, $00, $00, $00
org $10A0
resultado:
dcb $00, $00, $00, $00, $00, $00, $00, $00, $00, $00
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;