Commodore manía
Commodore 64 => Desarrollo => Ensamblador => Mensaje iniciado por: albanchez2k en Marzo 19, 2012, 11:12:06
-
Hola
Como ya sabréis, el 6502 solo puede realizar las operaciones de suma y resta con acarreo. Tanto la multiplicación como la división deben implementarse mediante algoritmo. Presento un algoritmo de multiplicación basado en el principio de desplazamiento aritmético. Esta escrito en el ensamblador kickass.
:BasicUpstart2(inicio) // "trampolín" basic llamador del programa
.const M = $10 //Multiplicando
.const m = $11 //multiplicador
.const r1 = $12 //resultado 1
.const r2 = $13 //resultado 2
.const max = $ff //valor maximo
.const min = $00 //valor minimo
.const ite = $08 //Iteraciones
.pc = $810 "Codigo"
// Codigo del programa
inicio:
sei //desactiva interrupciones
lda V1 //inicializo Multiplicando
sta M //
lda V2 //inicializo multiplicador
sta m //
lda #min //inicializo resultado
sta r2 //
ldx #ite //inicializo x
bucle:
lsr m //desplazo m a la derecha
if: bcc eif //si acarreo = 0 salto eif
clc
adc M //sumo M
eif: ror //roto acum a la derecha
ror r2 //roto r2 a la derecha
dex //decremento x
bne bucle //salto a bucle
fin:
sta r1 //muevo resul a r1
cli //activa interrupciones
rts // vuelve al BASIC
// Datos
V1: .byte 0 //Variable Multiplicador
V2: .byte 0 //Variable multiplicando
V1 es la variable de entrada del multiplicador y V2 del multiplicando.
r1 y r2 son los registros de resultado. r1 para el byte alto y r2 para el byte bajo.
Se puede probar mediante:
poke2109,MMM:poke2110,mmm
sys2064
print peek(18):print peek(19)
Teniendo en cuenta que los valores devuelto por los peek hay que convertirlos a hexadecimal. Por ejemplo:
MMM = 25
mmm = 13
25*13 = 325 –> Hex = 01 45
peek(18) = 1–> Hex = 01
peek(19) = 69 –> Hex = 45
-
Para un código no crítico hacer la multiplicación con un algoritmo puede valer pero para uno crítico (y a no ser que sea una multiplicación por potencia de 2) solo hay una solución: tablas.
PD: Por cierto, bienvenido ;D
-
Bienvenido albanchez2k! (vaya entrada al foro :P)
-
acabo de sacar una rutina de multiplicación muy rápida ...
/*
*************************************************************************************
RUTINA DE MULTIPLICACION RAPIDA * 320
ENTRADAS:
$fa = numero multiplicador (1 byte, rango efectivo = 0 < 204)
SALIDAS:
$fb-$fc = resultado del multiplicador * 320 (precisión 16 bits)
DETALLES:
Num. de ciclos = 51 (+12 contando ciclos del JSR/RTS)
Tamaño en memoria = 29 bytes
Max resultado teorico = 255 * 320 = 81600 ($013EC0)
(no cabe en 16 bits, habria que adaptar resultado a 3 bytes)
Max. resultado efectivo = 204 * 320 = 65280 ($FF00)
Si se quiere optimizar para menor tamaño, se pueden incluir las rotaciones
como una parte iterada dos veces por un bucle. Pero perdemos ciclos asi...
FECHA CREACION: 05-03-13 , ULT. REV.: 05-03-13 (LOBOGRIS)
***************************************************************************************
*/
fastMUL320:
// Descomponiendo, resultado de n * 320 = (256 * n) + (64 * n)
// ahora vamos a calcular 64*numero
// esto se consigue poniendo numero en la parte alta del resultado para obtener numero*256
// y desplazaremos (todos los 16 bits) de resultado a la derecha 2 veces para
// conseguir numero*64...
lda numero
clc // Primera rotacion lógica a la derecha (16 bits)
lsr
sta resultado+1 // Num. en parte alta resultado = multiplicar Num. * 256)
lda resultado
ror
sta resultado // Tras 1a rotación, resultado = 128 * numero
clc // 2a rotacion a la derecha (16 bits)
lda resultado+1
lsr
sta resultado+1
lda resultado
ror
sta resultado // aqui resultado = 64 * numero
// Ahora haremos resultado = (numero * 256) + (numero * 64)
lda numero // Recupera numero. Al ponerlo parte alta = numero * 256
adc resultado+1 // se añade a resultado*64 (parte alta es la única afectada)
sta resultado+1 // ¡Ahora resultado = 320 * numero!
rts
-
Adjunto por aqui un paquetillo con el codigo fuente completo y su prg con el que la he estado verificando...
Por cierto, la rutina es un desafio simplemente, es mucho más rápido usar tablas, claro. ;)
-
Lobogris no descansa!