División en asm con divisor impar
División en asm con divisor impar
Estoy limando cosillas y me he topado con una chorrada que me consume tiempo de proceso, durante la actualización de coordenadas de los sprites, hay un momento que tengo que dividir un entero (entre 0 y 60) entre 3. Lo hago decrementando con el típico bucle pero claro, hay veces que se repite 20 veces...
Imagino que se podría hacer una pirula con desplazamientos de bits pero llevo rato buscando y probando cosas y no doy con la tecla.
Imagino que se podría hacer una pirula con desplazamientos de bits pero llevo rato buscando y probando cosas y no doy con la tecla.
- antoniovillena
- Mensajes: 2621
- Registrado: 27 Sep 2015, 20:41
Re: División en asm con divisor impar
El inverso de la división es la multiplicación, así que tienes que multiplicar por 1/3. Tomando como 1 el valor 65536, 1/3 saldría (en hexadecimal queda más chulo) $5555. Por ponerte un ejemplo, intenta multiplicar 25 (en hexadecimal $19). Te sale $19*$5555= $8554D, de los 24 bits te quedas con los 8 bits superiores y tienes el resultado. Si no necesitas tanta precisión puedes hacer 8x8bits= 16bits. $19*$55= $84d y te quedas con la parte alta.Haplo escribió:Estoy limando cosillas y me he topado con una chorrada que me consume tiempo de proceso, durante la actualización de coordenadas de los sprites, hay un momento que tengo que dividir un entero (entre 0 y 60) entre 3. Lo hago decrementando con el típico bucle pero claro, hay veces que se repite 20 veces...
Imagino que se podría hacer una pirula con desplazamientos de bits pero llevo rato buscando y probando cosas y no doy con la tecla.
Re: División en asm con divisor impar
Otra opción, si tiene que ser muy rápido (si son sprites supongo que sí) y te sobran 61 bytes de memoria, es hacerte una tabla lookup.Haplo escribió:Estoy limando cosillas y me he topado con una chorrada que me consume tiempo de proceso, durante la actualización de coordenadas de los sprites, hay un momento que tengo que dividir un entero (entre 0 y 60) entre 3. Lo hago decrementando con el típico bucle pero claro, hay veces que se repite 20 veces...
Imagino que se podría hacer una pirula con desplazamientos de bits pero llevo rato buscando y probando cosas y no doy con la tecla.
Re: División en asm con divisor impar
Lo de la tabla ya lo había pensado pero me parecía algo en plan "tiro la toalla" ejejjeee
Si no doy con una solución "elegante" y más rápida que la que tengo, tiraré de tabla ciertamente.
Gracias por las ideas chicos.
Si no doy con una solución "elegante" y más rápida que la que tengo, tiraré de tabla ciertamente.
Gracias por las ideas chicos.
Re: División en asm con divisor impar
Bueno, muchas demos de los 90 para PC/VGA usaban tablas lookup. Es cierto que era para cosas más complicadas como senos, cosenos y cosas así, pero oye, también estabamos hablando de 486 a 33/66Mhz frente a Z80 a 3.5Mhz, yo creo que si la cosa es más rápida que el cálculo en sí, y hay sitio, no hay nada de malo en usar una tabla lookup. Yo cuando las descubrí me parecían cosa "de hackers" ("mira que listo este" pensaba)Haplo escribió:
Si no doy con una solución "elegante" y más rápida que la que tengo, tiraré de tabla ciertamente.
- mcleod_ideafix
- Mensajes: 831
- Registrado: 27 Sep 2015, 00:14
- Ubicación: Jerez de la Frontera
- Contactar:
Re: División en asm con divisor impar
Si lo que necesitas es velocidad, no hay nada más rápido que una tabla de lookup. Si encima te puedes permitir el lujo de que dicha tabla pueda comenzar en una posición de memoria múltiplo de 256 entonces tu código para dividir, por ejemplo, el valor del acumulador entre 3 y que el resultado se guarde de nuevo en A, te queda así:
Esto son: 4+7+7=21 ciclos de reloj. Si encima pudiera ser que el valor a dividir estuviera de antemano en L te ahorras 4 ciclos quedando la cosa en 14 ciclos.
Se puede hacer "trampa" pidiéndole al diseñador del core que te proporcione un puerto de E/S de la forma nnxx . Es decir, un puerto con dirección de 16 bits, donde la parte baja es fija (el valor xx) y que habría que escoger usando alguna combinación de bits que no se estuviera usando; y donde la parte alta, nn, correspondería al valor que quieres dividir entre tres. El periférico en ese puerto lo que haría sería coger los 8 bits altos de la dirección, dividirlos entre 3 por hardware, y el resultado darlo como resultado de la lectura del periférico. Así, para dividir el valor del acumulador entre 3 y retornarlo en el mismo acumulador quedaría así:
O sea, 11 ciclos
Código: Seleccionar todo
LD L,A
LD H,MSB de la direccion de la tabla
LD A,(HL)
Se puede hacer "trampa" pidiéndole al diseñador del core que te proporcione un puerto de E/S de la forma nnxx . Es decir, un puerto con dirección de 16 bits, donde la parte baja es fija (el valor xx) y que habría que escoger usando alguna combinación de bits que no se estuviera usando; y donde la parte alta, nn, correspondería al valor que quieres dividir entre tres. El periférico en ese puerto lo que haría sería coger los 8 bits altos de la dirección, dividirlos entre 3 por hardware, y el resultado darlo como resultado de la lectura del periférico. Así, para dividir el valor del acumulador entre 3 y retornarlo en el mismo acumulador quedaría así:
Código: Seleccionar todo
IN A,(xx)
http://www.zxuno.com
ZX-Uno · Clon de ordenador ZX Spectrum basado en FPGA
ZX-Uno · Clon de ordenador ZX Spectrum basado en FPGA
Re: División en asm con divisor impar
Un coprocesador matemático sería una cosa molona, aunque fuera uno ficticio con solo unas pocas funciones engorrosas (multiplicar por cosas que no son potencia de 2, dividir, elevar a, raiz cuadrada). Podría darse soporte a la parte de aritmética entera de 16 bits del AMD 9511 por ejemplo: http://www.hartetechnologies.com/manual ... %20FPU.pdfmcleod_ideafix escribió:O sea, 11 ciclosCódigo: Seleccionar todo
IN A,(xx)
Pero ya la estamos liando .. XD