Autor Tema: Rutina ASM para división de dos números de 16bits para PICs de 8 bits  (Leído 6825 veces)

0 Usuarios y 1 Visitante están viendo este tema.

Desconectado PICdevJerez

  • PIC10
  • *
  • Mensajes: 12
Hola chicos, aquí os comparto una rutina en ensamblador de cosecha propia para dividir dos números naturales (positivos) de 16bits en PICs de 8 bits.
Empleo desplazamientos en lugar de restas sucesivas, lo que hace que la rutina sea muy rápida (entre 330 y 350 ciclos de instrucción).
Además en muy cortita, por lo que ocupa poca memoria Flash del PIC.
Uso las instrucciones subwfb y lslf, que no están en los PIC más antiguos, pero se pueden sustituir fácilmente por un par de instrucciones en los PICs que no las admitan.
Seguramente habrá mejores subrutinas en este foro para dividir 16b:16b, pero como no las he encontrado, aquí tenéis mi humilde aportación.
Está implementada como una subrutina que podéis llamar con un simple CALL.
Os adjunto también el archivo .inc
Un saludo.
PICdevJerez

Código: ASM
  1. ;;DIVISION ENTERA DE NÚMEROS NATURALES 16bits:16bits
  2. ;;
  3. ;;Emplea la instrucción "subwfb", que se encuentra en
  4. ;;los Mid-Range 8 bits PICs (49 instrucciones o más)
  5. ;;
  6. ;;Realiza la división de dos números de 16bits
  7. ;;en aprox. 340 ciclos de instrucción
  8. ;;usando desplazamientos en lugar de restas sucesivas
  9. ;;
  10. ;;Necesita 2 variables de 8 bits:TEMPORAL y W_L
  11. ;;Para que funcione, las variables de 16bits han de estar
  12. ;;en el orden HIGH:LOW (como se puede ver en las equ)
  13. ;;es decir, en la posición más baja de la RAM el byte bajo
  14. ;;y en la siguiente posición más alta el byte alto
  15. ;;
  16. ;;Entrada: DIVIDENDO (16b) y DIVISOR(16b)
  17. ;;Salida: COCIENTE(16b) y RESTO(16b)
  18. ;;Borra DIVIDENDO, no altera DIVISOR
  19. ;;
  20. ;;Está implementada como una subrutina: DIVIDE
  21. ;;  PICdevJerez - Jerez de la Frontera - España
  22.  
  23.  
  24. #ifndef         Carry
  25.         #define Carry   STATUS,C
  26. #endif
  27.  
  28. #ifndef lsl16
  29.         lsl16   MACRO   File
  30.                 lslf    File,F
  31.                 rlf     (File+.1),F
  32.         endM
  33. #endif
  34.  
  35. ;;****************Estas líneas son un ejemplo ********************
  36. ;;**suprimir los punto y coma para su funcionamiento stand-alone**
  37. ;Temporal       equ     .127
  38. ;CocienteH      equ     .126
  39. ;Cociente       equ     .125
  40. ;RestoH         equ     .124
  41. ;Resto          equ     .123
  42. ;DividendoH     equ     .122
  43. ;Dividendo      equ     .121
  44. ;DivisorH       equ     .120
  45. ;Divisor        equ     .119
  46. ;W_L            equ     .118
  47. ;
  48. ;DIVIDENDO      equ     .6000   ;Constantes usadas como ejemplo
  49. ;DIVISOR        equ     .14     ;
  50. ;
  51. ;       movlw   HIGH DIVIDENDO
  52. ;       movwf   DividendoH
  53. ;       movlw   LOW DIVIDENDO
  54. ;       movwf   Dividendo
  55. ;       movlw   HIGH DIVISOR
  56. ;       movwf   DivisorH
  57. ;       movlw   LOW DIVISOR
  58. ;       movwf   Divisor
  59. ;;*****************************************************************
  60.  
  61. DIVIDE:
  62.         clrf    Temporal
  63.         clrf    CocienteH
  64.         clrf    Cociente
  65.         clrf    RestoH
  66.         clrf    Resto
  67. st:
  68.         btfsc   Temporal,4
  69.         return
  70.         incf    Temporal
  71.         lsl16   Cociente
  72.         lsl16   Resto
  73.         lsl16   Dividendo
  74.         btfsc   Carry
  75.         bsf     Resto,0
  76.         movf    Divisor,W
  77.         subwf   Resto,W
  78.         movwf   W_L
  79.         movf    DivisorH,W
  80.         subwfb  RestoH,W
  81.         btfss   Carry
  82.         goto    st
  83.         bsf     Cociente,0
  84.         movwf   RestoH
  85.         movf    W_L,W
  86.         movwf   Resto
  87.         goto    st
  88.  
  89. ;end

Desconectado alexhumbertoa

  • PIC10
  • *
  • Mensajes: 49
Re: Rutina ASM para división de dos números de 16bits para PICs de 8 bits
« Respuesta #1 en: 10 de Enero de 2015, 13:38:49 »
Gracias por compartirla, un detallazo :lol:
La protoboard es la mejor amiga del ruido.

Desconectado PICdevJerez

  • PIC10
  • *
  • Mensajes: 12
Re: Rutina ASM para división de dos números de 16bits para PICs de 8 bits
« Respuesta #2 en: 11 de Enero de 2015, 10:59:57 »
Gracias, alexhumbertoa.
Le he hecho un par de cambios a la rutina que posteé ayer para hacerla más rápida, ahora nos ahorramos hasta 25 ciclos de instrucción.
Según las pruebas que he hecho, se ejecuta en 315-331 ciclos.
Esta función también la podéis usar para dividir dos números de 8 bits y que os entregue el resultado con decimales.
¿Cómo? Muy sencillo: sólo tenéis que poner los 8 bits del dividendo en DIVIDENDOH (en la parte alta de DIVIDENDO), dejando los 8 bits más bajos a cero. El divisor lo dejáis igual que antes(poniendo los 8 bits del divisor en la parte baja y dejando DIVISORH a cero).
De esta manera obtendréis: en COCIENTEH la parte entera del resultado y en COCIENTE la parte decimal.
Como sólo usamos 8 bits para la parte decimal, os serán validas las 2 primeras cifras decimales del resultado.
Aquí tenéis un par de resultados reales que me ha dado el PIC16F1509:
55/7   =   7'8554 (en realidad es 7'8571)
255/7 = 36'4257  (en realidad es 36'4285)
Espero que os sea de utilidad,un saludo.
PICdevJerez


Código: ASM
  1. ;;DIVISION ENTERA DE NÚMEROS NATURALES 16bits:16bits
  2. ;;
  3. ;;Emplea la instrucción "subwfb", que se encuentra en
  4. ;;los Mid-Range 8 bits PICs (49 instrucciones o más)
  5. ;;
  6. ;;Realiza la división de dos números de 16bits
  7. ;;en aprox. 320 ciclos de instrucción
  8. ;;usando desplazamientos en lugar de restas sucesivas
  9. ;;
  10. ;;Necesita 2 variables de 8 bits:TEMPORAL y W_L
  11. ;;Para que funcione, las variables de 16bits han de estar
  12. ;;en el orden HIGH:LOW (como se puede ver en las equ)
  13. ;;es decir, en la posición más baja de la RAM el byte bajo
  14. ;;y en la siguiente posición más alta el byte alto
  15. ;;
  16. ;;Entrada: DIVIDENDO (16b) y DIVISOR(16b)
  17. ;;Salida: COCIENTE(16b) y RESTO(16b)
  18. ;;Borra DIVIDENDO, no altera DIVISOR
  19. ;;
  20. ;;Está implementada como una subrutina: DIVIDE
  21. ;;  PICdevJerez - Jerez de la Frontera - España
  22.  
  23.  
  24. #ifndef         Carry
  25.         #define Carry   STATUS,C
  26. #endif
  27.  
  28. #ifndef lsl16
  29.         lsl16   MACRO   File
  30.                 lslf    File,F
  31.                 rlf     (File+.1),F
  32.         endM
  33. #endif
  34.  
  35. ;;****************Estas líneas son un ejemplo ********************
  36. ;;**suprimir los punto y coma para su funcionamiento stand-alone**
  37. ;Temporal       equ     .127
  38. ;CocienteH      equ     .126
  39. ;Cociente       equ     .125
  40. ;RestoH         equ     .124
  41. ;Resto          equ     .123
  42. ;DividendoH     equ     .122
  43. ;Dividendo      equ     .121
  44. ;DivisorH       equ     .120
  45. ;Divisor        equ     .119
  46. ;W_L            equ     .118
  47. ;
  48. ;DIVIDENDO      equ     .6000   ;Constantes usadas como ejemplo
  49. ;DIVISOR        equ     .14     ;
  50. ;
  51. ;       movlw   HIGH DIVIDENDO
  52. ;       movwf   DividendoH
  53. ;       movlw   LOW DIVIDENDO
  54. ;       movwf   Dividendo
  55. ;       movlw   HIGH DIVISOR
  56. ;       movwf   DivisorH
  57. ;       movlw   LOW DIVISOR
  58. ;       movwf   Divisor
  59. ;;*****************************************************************
  60.  
  61. DIVIDE:
  62.         clrf    Temporal
  63.         clrf    CocienteH
  64.         clrf    Cociente
  65.         clrf    RestoH
  66.         clrf    Resto
  67. st:
  68.         btfsc   Temporal,4
  69.         return
  70.         incf    Temporal
  71.         lsl16   Cociente
  72.         lsl16   Dividendo
  73.         rlf     Resto
  74.         rlf     (Resto+.1)
  75.         movf    Divisor,W
  76.         subwf   Resto,W
  77.         movwf   W_L
  78.         movf    DivisorH,W
  79.         subwfb  RestoH,W
  80.         btfss   Carry
  81.         goto    st
  82.         bsf     Cociente,0
  83.         movwf   RestoH
  84.         movf    W_L,W
  85.         movwf   Resto
  86.         goto    st
  87.  
  88. ;end

Desconectado alexhumbertoa

  • PIC10
  • *
  • Mensajes: 49
Re: Rutina ASM para división de dos números de 16bits para PICs de 8 bits
« Respuesta #3 en: 11 de Enero de 2015, 20:44:34 »
Estoy seguro que nos será de mucha utilidad a muchos.  Buen trabajo!
La protoboard es la mejor amiga del ruido.


 

anything