uControl
Marzo 26, 2017, 11:45:15 *
Bienvenido(a), Visitante. Por favor, ingresa o regístrate.
¿Perdiste tu email de activación?

Ingresar con nombre de usuario, contraseña y duración de la sesión
 
   Inicio   Ayuda Buscar Ingresar Registrarse  
Páginas: [1]   Ir Abajo
  Imprimir  
Autor Tema: Multiplicación y Coma Flotante  (Leído 6709 veces)
0 Usuarios y 1 Visitante están viendo este tema.
SavageChicken
Amigo de uControl
PIC12F
******
Desconectado Desconectado

Sexo: Masculino
Mensajes: 314


Las oportunidades son puertas sin abrir


« : Julio 05, 2011, 06:25:50 »

Con la venia de los moderadores, quisiera aportar con un código para hacer multiplicaciones que ya compartí en otro foro. Paso a describirlo y finalmente ofrecerlo para quien lo desee.

Bien, vamos a jugar un poco con números binarios, y aprovechar ciertas ventajas que ellos tienen sobre todo al manipularlos con un microcontrolador.

  La mayoría de estas rutinas se basan en la siguiente lógica, "para multiplicar dos números entre ellos basta tomar una de las cifras y sumarla tantas veces como lo indique la segunda cifra". Este método funciona muy bien, pero no es para nada eficiente, imaginen multiplicar 17987 x 30653, estamos hablando de sumar "treinta mil seicientas cincuena y tres veces un número" por muy veloz que sea un PIC esto tomaría un buen tiempo, incluso el gasto en recursos (memoria, registros, ciclos, etc.) es enorme.

  Gracias a Dios tengo varios años, y si bien no me considero viejo, manejé una Sinclair TS-1000, con solo 2K de memoria, y muchos de los trucos y maravillas que se lograban con estas "home computers" se debían a la destreza de los programadores para aprovechar "las ventajas" de trabajar con los números binarios directamente.

  Muchos estarán bostezando y preguntándose hacia donde va toda esta cháchara, bueno dejemos la charla y vemos lo sustancial.

  Cuando trabajamos en binario, algunas cosas son más sencillas, en especial porque todos los números solo pueden tomar dos valores. Una ventaja por ejemplo es que para multiplicar cualquier número por 2, basta solo con desplazar los bit de dicho número un lugar hacia la izquierda, si no me creen vemos algunos ejemplos sencillos.

                     Decimal        Binario
                      3                 00011
(3 x 2)             6                 00110
(6 x 2)             12               01100

Probemos con otro número
                     Decimal         Binario
                      5                  00101
(5 x 2)             10                01010
(10 x 2)           20                10100

  Descubierto esta detalle interesante, podemos deducir, que si nos encontráramos con la necesidad de multiplicar un número por alguna potencia de 2, bastaría con correr los bits de dicho número tantas veces como lo indique el exponente y nos ahorraríamos muchas sumas.

  Por ejemplo si debo multiplicar 37 x 64, no necesito sumar 64 veces 37, ya que 2^6=64 basta con rotar a la izquierda 6 veces el valor binario de 37 y "voile"  obtengo el resultado de dicho producto (reduje 64 bucles de suma a solo 6 bucles de rlf), si no estan convencidos lo probemos...

                Decimal       Binario
                37                        100101
(37 x 64)   2368            100101000000   (el 37 movido 6 lugares a la izquierda ¡increible!)

  Como curiosidad está buena, es más, podría ser útil si siempre tenemos que hacer multiplicaciones en donde alguna de las dos cifras es potencia de 2, pero en la vida real esto es de poca utilidad. Pero a no desesperar, que el binario nos tiene preparadas más sorpresas aún...

  ¿Cómo nos pueden ayudar estos 1 y 0 en los productos de números cualesquiera?
  Bueno, veamos primero, la manera en que haríamos una multiplicación en binario de dos números, tal como nos enseñaron en el colegio. Utilizaremos dos números pequeños para no complicarnos, pero el método sirve para cualquier número:

                 Decimal              Binario
                 5                                 0101
                 x 11                          x 1011
                                            -------------
                                                    0101      <- El número 5 sin corrimiento
                                                  0101        <- El número 5 corrido 1 lugar a la izquierda
                                                0000          <- En este cáso el dígito del segundo factor es 0, no se suma nada
                                              0101            <- El número 5 corrido 3 lugares a la izquierda
                                            -------------
                 = 55                      0110111

  Como podrán ver hay algo que salta a la vista y es que el producto de dos números en binario no es otra cosa que ir desplazando a la izquierda el valor binario de uno de los factores tantas veces como dígitos tenga el segundo factor, y hacer la suma sucesiva de estos valores desplazados, sólamente cuando el dígito del segundo factor valga 1.

  Con esta información ya podemos hacer un código bastante sencillo que realice multiplicaciones de números tan grandes como queramos, fácilmente podemos trabajar con números de 16, 32 o 64 bits, bastará con hacer rotaciones y sumas. Pensemos ahora en el producto que pusimos de ejemplo en un principio (17987 x 30653), estos son números de 16 bits, y hemos reducido la operatoria de más de 30000 sumas a solo 16 rotaciones y alrededor de 16 sumas ¡Valía la pena usar binarios verdad!.

  Bien pero aún hay más. Muchas consultas son por números decimales y no solo por enteros y sinceramente es más sencillo de lo que parece, cuando uno multiplica dos números enteros como 31416 x 27182 obtiene 853949712 y si multiplicamos 3,1416 x 2,7182 obtenemos 8,53949712 ¿acaso no es el mismo número? todo lo que los diferencia es una coma, simplemente debemos multiplicar los factores como si ellos fueran enteros, guardar en un par de registros la posición de la coma de cada factor a multiplicar y despues desplazar en el resultado la posición de la coma el equivalente a la suma de las posiciones que tenían las comas en los factores que fueron multiplicados, tal cual lo hacemos cuando multiplicamos en forma manual.

  Finalmente nos queda algo relativamente sencillo, habiendo entendido esto hay que hacer el código.

Código:
;**********************************************************************
;                                                                     *
;    Filename:    Multiplicar.asm                                   *
;    Date:          30/10/2010                                        *
;    File Version:  1.1                                               *
;                                                                     *
;    Author:        Ruben Arranz                                      *
;    Company:       Electronics Design                                *
;                                                                     *
;                                                                     *
;**********************************************************************
;                                                                     *
;    Files required:                                                  *
;                    16F648A.lkr                                      *
;                                                                     *
;                                                                     *
;**********************************************************************
;                                                                     *
;    Notes:                                                           *
;                                                                     *
;                                                                     *
;                                                                     *
;                                                                     *
;**********************************************************************
list      p=16F648A           ; list directive to define processor
#include <p16F648A.inc>       ; processor specific variable definitions
errorlevel  -302              ; suppress message 302 from list file
__CONFIG   _CP_OFF & _DATA_CP_OFF & _LVP_OFF & _BOREN_OFF & _MCLRE_OFF & _WDT_OFF & _PWRTE_ON & _INTOSC_OSC_NOCLKOUT
; Para numeros de 32 bits, necesitamos colocar el resultado en un numero de 64 bits es decir 8 Registros de Memoria
Resultado_B7 equ 0x20 ; Byte mas significativo del Resultado
Resultado_B6 equ 0x21
Resultado_B5 equ 0x22
Resultado_B4 equ 0x23
Resultado_B3 equ 0x24
Resultado_B2 equ 0x25
Resultado_B1 equ 0x26
Resultado_B0 equ 0x27 ; Byte menos significativo del Resultado
ValInt_B7 equ 0x28 ; Byte mas significativo del Valor Intermedio
ValInt_B6 equ 0x29
ValInt_B5 equ 0x2A
ValInt_B4 equ 0x2B
ValInt_B3 equ 0x2C
ValInt_B2 equ 0x2D
ValInt_B1 equ 0x2E
ValInt_B0 equ 0x2F ; Byte menos significativo del Valor Intermedio
Factor_A_B3 equ 0x30 ; Byte mas significativo del Factor A
Factor_A_B2 equ 0x31
Factor_A_B1 equ 0x32
Factor_A_B0 equ 0x33 ; Byte menos significativo del Factor A
Factor_B_B3 equ 0x34 ; Byte mas significativo del Factor B
Factor_B_B2 equ 0x35
Factor_B_B1 equ 0x36
Factor_B_B0 equ 0x37 ; Byte menos significativo del Factor B
Coma_R equ 0x38 ; Posicion de la coma del Resultado
Coma_A equ 0x39 ; Posicion de la coma del Factor A
Coma_B equ 0x3A ; Posicion de la coma del Factor B
Contador equ 0x3B ; Esta variable sera el contador de los desplazamientos que debemos hacer
Auxiliar_A equ 0x03C ; Variable Auxiliar para propositos generales
Auxiliar_B equ 0x03D ; Variable Auxiliar para propositos generales
Auxiliar_C equ 0x03E ; Variable Auxiliar para propositos generales
Auxiliar_D equ 0x03F ; Variable Auxiliar para propositos generales
ResDec_9 equ 0x040
ResDec_8 equ 0x041
ResDec_7 equ 0x042
ResDec_6 equ 0x043
ResDec_5 equ 0x044
ResDec_4 equ 0x045
ResDec_3 equ 0x046
ResDec_2 equ 0x047
ResDec_1 equ 0x048
ResDec_0 equ 0x049
ResASC_20 equ 0x050
ResASC_19 equ 0x051
ResASC_18 equ 0x052
ResASC_17 equ 0x053
ResASC_16 equ 0x054
ResASC_15 equ 0x055
ResASC_14 equ 0x056
ResASC_13 equ 0x057
ResASC_12 equ 0x058
ResASC_11 equ 0x059
ResASC_10 equ 0x05A
ResASC_9 equ 0x05B
ResASC_8 equ 0x05C
ResASC_7 equ 0x05D
ResASC_6 equ 0x05E
ResASC_5 equ 0x05F
ResASC_4 equ 0x060
ResASC_3 equ 0x061
ResASC_2 equ 0x062
ResASC_1 equ 0x063
ResASC_0 equ 0x064
Espacio equ 0x065
;**********************************************************************
RESET_VECTOR CODE 0x000 ;Vector de Reset del Procesador
goto Multiplicar
VECT_INT CODE 0x004 ;Vector de Interrupcion del Procesador
goto Multiplicar
MAIN CODE 0x005
Multiplicar
; Me gusta partir explicandome a mi mismo lo que quiero hacer, y luego realizar las lineas de comando
; En pocas palabras vamos a tomar el valor almacenado en Factor A y lo desplazaremos a la izquierda tantas veces...
; ...como digitos binarios tenga el Factor B, este desplazamiento quedara almacenado en Valor Intermedio, en cada...
; ..ocacion  que el digito binario analizado del factor B sea 1 sumaremos el valor intermedio al Resultado
; No tendremos en consideracion cual de los dos factores es mayor, siempre se tomara el valor del factor A...
; ... para hacer el desplazamiento y se analizara el factor B para hacer las sumas.
; Comenzamos limpiando las variables que usaremos
clrf Resultado_B0
clrf Resultado_B1
clrf Resultado_B2
clrf Resultado_B3
clrf Resultado_B4
clrf Resultado_B5
clrf Resultado_B6
clrf Resultado_B7
clrf ValInt_B0
clrf ValInt_B1
clrf ValInt_B2
clrf ValInt_B3
clrf ValInt_B4
clrf ValInt_B5
clrf ValInt_B6
clrf ValInt_B7
clrf Contador
clrf Auxiliar_A
clrf Auxiliar_B
movlw 0x30
movwf Espacio
; Esta rutina considera que las variables Factor_A y Factor_B fueron previamente cargadas
; Siendo que en virtud del valor de B se realizaran las sumas sucesivas, intentaremos ver cual es el bit mas significativo...
; ...de este factor para no hacer loops innecesarios.
; Esto evitara que hagamos por ejemplo 32 loops cuando estamos multiplicando numeros pequeños.
movfw Factor_B_B3 ; Me fijo si hay algun bit en 1 en el byte mas significativo
movwf Auxiliar_A ; Aprovecho la pasada para guardar este dato en la Variable Auxiliar
btfsc STATUS,Z ; La existencia de algun bit en 1 la puedo detectar en el valor Z del Status
goto TestByte2 ; No habiendo ninguno bit en 1 sigo con el siguiente byte
movlw 0x18 ; Habiendo algun bit en 1 el 0x18 corresponde al valor minimo de loops que debere hacer
movwf Contador ; Almaceno este dato en el Contador
goto DeterminaLoops ; Vamos a ver en forma mas detallada cuantos loops deberemos hacer
TestByte2 movfw Factor_B_B2 ; Me fijo si hay algun bit en 1 en el byte siguiente
movwf Auxiliar_A ; Aprovecho la pasada para guardar este dato en la Variable Auxiliar
btfsc STATUS,Z ; La existencia de algun bit en 1 la puedo detectar en el valor Z del Status
goto TestByte1 ; No habiendo ninguno bit en 1 sigo con el siguiente byte
movlw 0x10 ; Habiendo algun bit en 1 el 0x10 corresponde al valor minimo de loops que debere hacer
movwf Contador ; Almaceno este dato en el Contador
goto DeterminaLoops ; Vamos a ver en forma mas detallada cuantos loops deberemos hacer
TestByte1 movfw Factor_B_B1 ; Me fijo si hay algun bit en 1 en el byte siguiente
movwf Auxiliar_A ; Aprovecho la pasada para guardar este dato en la Variable Auxiliar
btfsc STATUS,Z ; La existencia de algun bit en 1 la puedo detectar en el valor Z del Status
goto TestByte0 ; No habiendo ninguno bit en 1 sigo con el siguiente byte
movlw 0x08 ; Habiendo algun bit en 1 el 0x08 corresponde al valor minimo de loops que debere hacer
movwf Contador ; Almaceno este dato en el Contador
goto DeterminaLoops ; Vamos a ver en forma mas detallada cuantos loops deberemos hacer
TestByte0 movfw Factor_B_B0 ; En este caso veremos solo el detalle del byte
movwf Auxiliar_A ; Guardamos este dato en la Variable Auxiliar
DeterminaLoops movlw 0x08 ; En la ultima etapa, del valor maximo de loops probables (0x08)...
movwf Auxiliar_B ; ...deberemos descontarle al contador de loops una vuelta por cada bit en 0...
DetLoop_A rlf Auxiliar_A,f ; ...y deteniendonos en el primer bit en 1, esto visto desde el bit de mayor peso hacia abajo
btfsc STATUS,C ; Por eso vamos sacando los bit de mayor peso y chequeamos si estan en 1
goto SumaLoop ; Si esta en 1 paramos de decrementar
decfsz Auxiliar_B,f ; Por el contrario si tenemos un 0 decrementamos el valor que se le sumara al contador...
goto DetLoop_A ; ...y volvemos para chequear el siguiente bit
SumaLoop movfw Auxiliar_B ; Finalmente ponemos en el contador el valor de loops...
addwf Contador,f ; Que deberan realizarse para efectuar el producto
; Si lo preferimos podemos cargar el contador con los 32 loops, esto ahorrara memoria en el PIC...
; ...Pero tomara mas ciclos la ejecucion total de la multiplicacion, la decicion es nuestra.
; movlw 0x20 ; Cargo el Contador de loops
; movwf Contador
; Bien llego el momento de multiplicar
; En primera instancia, pasamos el Factor A a la variable ValInt
movfw Factor_A_B0
movwf ValInt_B0
movfw Factor_A_B1
movwf ValInt_B1
movfw Factor_A_B2
movwf ValInt_B2
movfw Factor_A_B3
movwf ValInt_B3
; Luego generamos el loop
; La idea es ir testeando uno a uno los bits del Factor B, para descubrir si son 1 o 0
; Del bit menos significativo al mas significativo
LoopMultip bcf STATUS,C ; Utilizamos el bit de acarreo para testear esto, por eso primero lo ponemos a0
rrf Factor_B_B3,f ; Rotamos ahora los 4 bytes
rrf Factor_B_B2,f
rrf Factor_B_B1,f
rrf Factor_B_B0,f
btfsc STATUS,C ; No fijamos que salio en el ultimo bit
call SumarFactor_A ; Si hay un uno llamamos a la rutina de Suma...
call RotaFactor_A ; ... mientras que en cualquier caso 1 o 0 debemos rotar el factor A
decfsz Contador,f ; Finalmente decrementamos el contador hasta llegar a 0
goto LoopMultip ; Si todavia no llegamos a 0 nos mantenemos en este loop
; Si se requiere convertimos la cifra a un valor decimal
; ATENCION: La convercion del valor Hexadecimal a Decimal destruye el resultado en Hexadecimal
call Hexadec_BDC
;Finalmente lo mas sencillo, decidir que posicion ocupa la coma en el resultado final
clrf Coma_R
movfw Coma_A
addwf Coma_B,w
movwf Coma_R
; Si se requiere acomodar el resultado para mostrarlo en un display o algo similar
call BCD_ASCII
goto Finalizar ; Terminada la multiplicacion, salimos de la subrutina
; Simplemente rotamos todos los bytes para la proxima etapa
RotaFactor_A bcf STATUS,C
rlf ValInt_B0,f
rlf ValInt_B1,f
rlf ValInt_B2,f
rlf ValInt_B3,f
rlf ValInt_B4,f
rlf ValInt_B5,f
rlf ValInt_B6,f
rlf ValInt_B7,f
return
; Vamos sumando en la variable resultado los valores intermedios cuando corresponde
; Esta suma se hace byte a byte y en caso de suceder un acarreo se llama a una subrutina que incrementa el siguiente byte
SumarFactor_A bcf STATUS,C
movfw ValInt_B0
addwf Resultado_B0,f
btfsc STATUS,C
call Incremento_B1
bcf STATUS,C
movfw ValInt_B1
addwf Resultado_B1,f
btfsc STATUS,C
call Incremento_B2
bcf STATUS,C
movfw ValInt_B2
addwf Resultado_B2,f
btfsc STATUS,C
call Incremento_B3
bcf STATUS,C
movfw ValInt_B3
addwf Resultado_B3,f
btfsc STATUS,C
call Incremento_B4
bcf STATUS,C
movfw ValInt_B4
addwf Resultado_B4,f
btfsc STATUS,C
call Incremento_B5
bcf STATUS,C
movfw ValInt_B5
addwf Resultado_B5,f
btfsc STATUS,C
call Incremento_B6
bcf STATUS,C
movfw ValInt_B6
addwf Resultado_B6,f
btfsc STATUS,C
call Incremento_B7
bcf STATUS,C
movfw ValInt_B7
addwf Resultado_B7,f
return
; Esta seccion es llamada cuando en la suma ocurre un acarreo, este acarreo se traslada al siguiente byte...
; ...incrementandolo, en caso de que este incremento genere otro acarreo, se sigue trasladando el acarreo al byte siguiente
Incremento_B1 incf Resultado_B1,f
btfss STATUS,Z
return
Incremento_B2 incf Resultado_B2,f
btfss STATUS,Z
return
Incremento_B3 incf Resultado_B3,f
btfss STATUS,Z
return
Incremento_B4 incf Resultado_B4,f
btfss STATUS,Z
return
Incremento_B5 incf Resultado_B5,f
btfss STATUS,Z
return
Incremento_B6 incf Resultado_B6,f
btfss STATUS,Z
return
Incremento_B7 incf Resultado_B7,f
return
; Rutina de Conversion de Hexadecima a Decimal (Esta rutina no es mia, solo la adapte)
; Hexadecimal (Resultado_B7 a Resultado_B0) -> Decimal (ResDec_9-ResDec_0)
; Para una Multiplicacion de FFFFFFFF x FFFFFFFF (Que es el maximo numero a multiplicar por nosotros)
; obtenemos FFFFFFFE00000001 y en decimal 18446744065119617025 para representar este numero utilizamos u nibble por digito
; por lo tanto necesitaremos 10 bytes para almacenarlo
Hexadec_BDC bcf STATUS,C
movlw   0x40 ; este valor es la cantidad de bits del numero hexadecimal a convertir (64 bits)
movwf   Contador
clrf ResDec_9
clrf ResDec_8
clrf ResDec_7
clrf ResDec_6
clrf ResDec_5
clrf ResDec_4
clrf ResDec_3
clrf ResDec_2
clrf ResDec_1
clrf ResDec_0
Hex_BCD_1 rlf Resultado_B0,f
rlf Resultado_B1,f
rlf Resultado_B2,f
rlf Resultado_B3,f
rlf Resultado_B4,f
rlf Resultado_B5,f
rlf Resultado_B6,f
rlf Resultado_B7,f
rlf ResDec_0,f
rlf ResDec_1,f
rlf ResDec_2,f
rlf ResDec_3,f
rlf ResDec_4,f
rlf ResDec_5,f
rlf ResDec_6,f
rlf ResDec_7,f
rlf ResDec_8,f
rlf ResDec_9,f
decfsz Contador,f
goto Hex_BCD_2
return
Hex_BCD_2 movlw ResDec_0
call Hex_BCD_3
movlw ResDec_1
call Hex_BCD_3
movlw ResDec_2
call Hex_BCD_3
movlw ResDec_3
call Hex_BCD_3
movlw ResDec_4
call Hex_BCD_3
movlw ResDec_5
call Hex_BCD_3
movlw ResDec_6
call Hex_BCD_3
movlw ResDec_7
call Hex_BCD_3
movlw ResDec_8
call Hex_BCD_3
movlw ResDec_9
call Hex_BCD_3
goto Hex_BCD_1
Hex_BCD_3 movwf FSR
movlw 0x03
addwf INDF,f
btfss INDF,3
subwf INDF,f
movlw 30H
addwf INDF,f
btfss INDF,7
subwf INDF,f
return
; Esta seccion convierte el número de decimal a caracteres ASCII para mostrar en un display (Seccion Nueva)
BCD_ASCII movlw 0x15 ;Limpiamos la conversion ASCII anterior, llenando de 0 todos los dígitos
movwf Auxiliar_A
movlw ResASC_0
movwf FSR
LimpiaASCII movlw 0x30
movwf INDF
decf FSR,f
decfsz Auxiliar_A,f
goto LimpiaASCII
movlw 0x0A ; Meto en elcontador la cantidad de BCD's a transformar
movwf Contador
movlw ResASC_20 ; Cargo en Auxiliar_B la direccion con valores de más peso de los ASCII
movwf Auxiliar_B
movlw ResDec_9 ; Hago lo mismo pero ahora con las direccion de los valores de más peso de los BCD en Auxiliar_A
movwf Auxiliar_A
ASCII_Loop_1 movwf FSR ; Direcciono indirectamente al resultado en BCD
movfw INDF ; Cargo el dato en BCD
swapf INDF,w ; Ttrabajamos con la parte alta de este BCD
andlw 0x0F ; limpio la parte que no me sirve...
addlw 0x30 ; ...y lo convierto en un valos ASCII
movwf Auxiliar_C ; Guardo la conversion en Auxiliar_C
call VerifComa ; Rutina que chequéa si corresponde colocar la coma
movfw Auxiliar_B ; Direcciono indirectamente la actual posición ASCII
movwf FSR
movfw Auxiliar_C ; Meto el valor convertido en la dirección correspondiente
movwf INDF
incf Auxiliar_B,f ; Apunto a donde se dejará el próximo valor ASCII
movfw Auxiliar_A ; Direcciono indirectamente al resultado en BCD de nuevo
movwf FSR ; Cargo el dato en BCD, Ahora trabajaremos con la parte baja
movfw INDF
andlw 0x0F ; limpio la parte que no me sirve...
addlw 0x30 ; ...y lo convierto en un valos ASCII
movwf Auxiliar_C ; Guardo la conversion en Auxiliar_C
call VerifComa ; Rutina que chequéa si corresponde colocar la coma
movfw Auxiliar_B ; Direcciono indirectamente la actual posición ASCII
movwf FSR
movfw Auxiliar_C ; Meto el valor convertido en la dirección correspondiente
movwf INDF
incf Auxiliar_A,f ; Apunto a donde se tomaran los dos siguientes valores BCD
incf Auxiliar_B,f ; Apunto a donde se dejara el proximo valor ASCII
movfw Auxiliar_A ; Dejo en w el valor de la proxima dirección BCD
decfsz Contador,f ; Verifico si hemos llegado al final del loop
goto ASCII_Loop_1
; En esta seccion eliminamos los ceros antes del primer valor significativo o antes de la coma y los ceros despues del...
; ...último valor significativo.
movlw ResASC_20 ; Direcciono indirectamente la actual posición ASCII
movwf FSR
movlw 0x00 ; Utilizo Auxiliar_A como un contador para saber desde donde debo desplazar los dígitos más significativos
movwf Auxiliar_A
ASCII_Loop_2 movfw INDF
xorlw 0x30 ; Comparo dígito a dígito de izquierda a derecha...
btfss STATUS,Z ; ...si los valores son 0
goto ASCII_Loop_3 ; si llego a un dígito que no es 0 salgo del loop
incf FSR,f ; si es 0 direcciono el siguiente digito...
incf Auxiliar_A,f ;... e incremento el contador que indica cuantos digitos hay en 0
goto ASCII_Loop_2 ; y seguimos testeando
ASCII_Loop_3 movfw INDF ; Antes de terminar esta seccion
xorlw 0x2C ; comparo el último dígito que no fue 0 para ver...
btfsc STATUS,Z ; si el dígito tenia una ,
decf Auxiliar_A,f ; tomo el dígito anterior para que el resultado quede 0,XXXX
call Corre_ASCII ; Llamamos a la rutina que desplaza los dígitos
movlw ResASC_0
movwf FSR
ASCII_Loop_4 movfw INDF
xorlw 0x30
btfss STATUS,Z
goto ASCII_Loop_5
movlw 0x20
movwf INDF
decf FSR,f
goto ASCII_Loop_4
ASCII_Loop_5 movfw INDF
xorlw 0x2C
btfss STATUS,Z
return
movlw 0x20
movwf INDF
return
VerifComa movfw Coma_R
sublw ResASC_0
xorwf Auxiliar_B,w
btfss STATUS,Z
return
movfw Auxiliar_B ; Direcciono indirectamente la actual posición ASCII
movwf FSR
movlw 0x2C ; Meto una coma en la posición adecuada
movwf INDF
incf Auxiliar_B,f
return
Corre_ASCII movlw 0x15
movwf Auxiliar_B
movlw ResASC_19
movwf FSR
Loop_C_ASC_2 movfw INDF
decf FSR,f
movwf INDF
incf FSR,f
incf FSR,f
decfsz Auxiliar_B,f
goto Loop_C_ASC_2
decfsz Auxiliar_A,f
goto Corre_ASCII
return
Finalizar
end
; Si la estamos ocupando como una subrutina en lugar del end colocamos un return

P/D: No se por que razón no conserva los "tabs" de principio de línea
En línea

No hay preguntas tontas...
Solo hay tontos que no preguntan.
Ariel
Global Moderator
dsPIC
****
Desconectado Desconectado

Sexo: Masculino
Mensajes: 10751



WWW
« Respuesta #1 : Julio 05, 2011, 06:29:21 »

¡Muy buen post! Wink

Todo este tipo de dato es bienvenido.

Gracias!
En línea

Si cualquier habilidad que aprende un niño será obsoleta antes de que la use, entonces, ¿qué es lo que tiene que aprender? La respuesta es obvia:
La única habilidad competitiva a largo plazo es la habilidad para aprender
“. Seymour Papert
el_vpi
Moderador
PIC18F
******
Desconectado Desconectado

Mensajes: 1348



« Respuesta #2 : Julio 05, 2011, 11:05:25 »

Ruben, MUY BUEN POST !!
realmente en su momento habia que hacer malabares con un par de K`s de memoria y micros corriendo a 4 Mhz (olvidate del nuevo 8087). Creo que nos despertaba la imaginacion al maximo para poder hacer algo.
Lo mismo pasaba con logica combinacional cuando tenias que decodificar un banco de memoria o e/s dentro de los larguisimos 64K del mapa.

Gracias. Saludos, el_vpi.
En línea
Leon Pic
Moderator
dsPIC
***
Desconectado Desconectado

Sexo: Masculino
Mensajes: 5694


Cumulonimbus


WWW
« Respuesta #3 : Julio 06, 2011, 09:56:24 »

Muy buena explicación rolleyes2 rolleyes2
En línea

Jesús dijo, yo soy el CAMINO, la VERDAD y la VIDA, nadie llega al PADRE si no es por mi.
SavageChicken
Amigo de uControl
PIC12F
******
Desconectado Desconectado

Sexo: Masculino
Mensajes: 314


Las oportunidades son puertas sin abrir


« Respuesta #4 : Julio 06, 2011, 02:27:52 »

Gracias por la chincheta  Wink
En línea

No hay preguntas tontas...
Solo hay tontos que no preguntan.
HJ
Moderador
dsPIC
******
Desconectado Desconectado

Sexo: Masculino
Mensajes: 5662



« Respuesta #5 : Julio 06, 2011, 02:35:05 »

Muy buen aporte.

Saludos

P.D.: Si mal no recuerdo había un libro tapa roja y blanca sobre el microprocesador 6800, que traía varias operaciones binarias con muchos ejemplos. Lamentablemente lo presté y se perdió. No recuerdo el autor.
En línea

"si te lo dicen se te olvida, si lo lees lo aprendes; pero si lo haces realmente lo entiendes"
"Cuando llegue la inspiración, que me encuentre trabajando" [Pablo Picasso]
Ariel
Global Moderator
dsPIC
****
Desconectado Desconectado

Sexo: Masculino
Mensajes: 10751



WWW
« Respuesta #6 : Julio 06, 2011, 03:26:06 »

Lástima!

En la red se puede ver este, que de blanco no tiene nada pero que puede aportar algo:

En línea

Si cualquier habilidad que aprende un niño será obsoleta antes de que la use, entonces, ¿qué es lo que tiene que aprender? La respuesta es obvia:
La única habilidad competitiva a largo plazo es la habilidad para aprender
“. Seymour Papert
Diogenes
Visitante
« Respuesta #7 : Julio 06, 2011, 04:46:34 »

Hola, muy bueno el post. También sirven de mucho estos links:

http://homepage.mac.com/randyhyde/webster.cs.ucr.edu/www.artofasm.com/DOS/pdf/ch09.pdf

Aunque los ejemplos de assembler se basan en X-86 los algoritmos se pueden aplicar para otras plataformas.

También un libro fundamental es este:

El arte de programar ordenadores. Vol II: Algoritmos seminuméricos. de Donald Knuths

Saludos !



En línea
brian_etn
PIC10F
*
Desconectado Desconectado

Sexo: Masculino
Mensajes: 48



« Respuesta #8 : Septiembre 30, 2011, 11:01:52 »

ey buena esa , a veces uno olvida aplicar todos esos conocimientos que nos
exigieron en las clases basicas de digital y que (claro) parecian solo pavadas
en ese entonces.

gracias por removernos el brain!!
 bang
En línea
SavageChicken
Amigo de uControl
PIC12F
******
Desconectado Desconectado

Sexo: Masculino
Mensajes: 314


Las oportunidades son puertas sin abrir


« Respuesta #9 : Octubre 03, 2011, 04:38:50 »

Que bueno que te gustó Brian, la idea es esa justamente, ocupar conceptos sencillos que permiten hacer las cosas de un modo más eficiente.

Salud  Cool
En línea

No hay preguntas tontas...
Solo hay tontos que no preguntan.
Páginas: [1]   Ir Arriba
  Imprimir  
 
Ir a:  

Impulsado por MySQL Impulsado por PHP Powered by SMF 1.1.21 | SMF © 2011, Simple Machines
SMFAds for Free Forums
XHTML 1.0 válido! CSS válido!
Página creada en 0.162 segundos con 25 consultas. (Pretty URLs adds 0.021s, 2q)