Autor Tema: Sera ASM ???  (Leído 15926 veces)

0 Usuarios y 5 Visitantes están viendo este tema.

Desconectado Resistencio

  • PIC12
  • **
  • Mensajes: 82
Sera ASM ???
« en: 17 de Marzo de 2007, 02:32:19 »
Hola, muchachos, muchachas, chicos, chicas, señoras y señores...soy relativamente nuevo en esto de los PIC´s, de hecho todavia tengo el "celofan" puesto...lo cierto es que el ASM es lo unico que aprendi, y de hecho, creanme, para mi que aprendi electronica, con el "cerebro magico" o con la "Lupin", como lei por ahi...es mucho decir...

Como les decia, aprendi, de tanto leer codigo...y ahora, de leerlos a ustedes...quizas alguien pueda decirme si esto es ASM, y si asi es, como se entiende, que significa, lo que sigue abajo...

El codigo tiene que ver con la siguiente MACRO:

;DELAY CYCLES instruction cycles

Delay      macro    Time
  if (Time==1)
                      nop
                      exitm
endif

  if (Time==2)
                     goto   $+1
                     exitm
endif

  if (Time==3)
                     nop
                     goto   $+1
                     exitm
endif

  if (Time==4)

                     goto  $+1
                     goto  $+1
                     exitm
endif

Asi hasta:

  if (Time==7)
                      goto  $+1
                      goto  $+1
                      goto  $+1
                      nop
                      exitm
endif

Despues:

 if (Time%4==0)
                      movlw   (Time-4)/4
                      call        Delay_us
                      exitm
endif

 if (Time%4==1)
                       movlw   (Time-5)/4
                       call        Delay_us
                       nop
                       exitm
endif

 if (Time%4==2)
                       movlw   (Time-6)/4
                       call        Delay_us
                       goto      $+1
                       exitm
endif

 if (Time%4==3)
                       movlw     (Time-7)/4
                       call          Delay_us
                        goto        $+1
                        nop
                        exitm
endif
                        endm

Bueno esa es la MACRO, que esta en medio de ASM, que si entiendo...

En el programa llama a esta MACRO, con:

                        Delay11 o Delay21 o Delay45 o Delay8

Lo cual parecen ser las variables de alguna demora...

La rutina Delay_us es:

;Delay 4w+4 cycles (including call.return and movlw) (0=256)

Delay_us     ADDLW  -1        ;precise delays used in I/O  (esto esta buenisimo de sumar -1)
                  btfss    STATUS,Z
                  goto    Delay_us
                  return


Estas rutinas estan en un soft para emular un mouse por PS/2...

Si alguien puede explicarme como anda la MACRO, si es ASM o es un "trozo" de BASIC ???

Si consideran que falta algun otro dato, por favor avisenme !!!

Bueno, me voy a comer un alfajor y espero algun "cerebro inteligente", que me responda...tambien puede ser alguien inspirado...o simplemente con ganas de escribirme...comparto el "alfajor"  :-) con el primero que me de una pista !!!  :mrgreen:

Desconectado BrunoF

  • Administrador
  • DsPIC30
  • *******
  • Mensajes: 3865
Re: Sera ASM ???
« Respuesta #1 en: 17 de Marzo de 2007, 03:44:42 »
Lo que expones es codigo ASM y es una MACRO.

Lo que hace con tantos "IF" es intentar simular una especie de "SWITCH"(en C y similares) o "CASE"(VB y similares) para seleccionar el retardo segun el valor "Time" Recibido.

Ejemplo: si en el programa pongo: Delay 7

Lo que en realidad se "ensambla" en el PIC es:
                      goto  $+1
                      goto  $+1
                      goto  $+1
                      nop

goto es una instruccion de 2 ciclos de ejecucion. Por lo que si hay 3 gotos y un nop, en total tenes 7 ciclos de instruccion. Si usas un cristal de 4mhz esto equivale a 7us.

Hay hasta Time = 7 porque son tan pequeñas las demoras que no se puede hacer un caso general para ellas.

Si la demora es mayor, entonces si podes y por eso surge por ejemplo:

if (Time%4==1)
                       movlw   (Time-5)/4
                       call        Delay_us
                       nop
                       exitm
endif

El % en este lenguaje si mal no me equivoco es el resto(mod) de una division con cociente entero.
Ejemplo: 41%4= 1 porque 40/4 es 10, pero el resto es 1. Y eso es lo que interesa en este caso. El resto.El mod.

Si dividis a cualquier numero por 4, podes obtener un resto igual a 0,1,2 o 3. Si o si esas son todas las oportunidades.
Lo unico que hace esa MACRO es calcular los tiempos de demora segun el delay que desees.

"All of the books in the world contain no more information than is broadcast as video in a single large American city in a single year. Not all bits have equal value."  -- Carl Sagan

Sólo responderé a mensajes personales, por asuntos personales. El resto de las consultas DEBEN ser escritas en el foro público. Gracias.

Desconectado Resistencio

  • PIC12
  • **
  • Mensajes: 82
Re: Sera ASM ???
« Respuesta #2 en: 17 de Marzo de 2007, 19:07:11 »
Bien, BRUNO, ya tengo una pista...ahora, entre tanta MACRO, como sabe el valor que debe tomar la demora...por ejemplo si en el programa, llamo a esta MACRO con DELAY 21, que valores toma ??? (aca parece que la demora sera de 21 us) pero como construye, esos 21 us ???

Por otro lado, el MAPLAB, reconoce IF, como ASM???...pregunto esto por que en otro "hilo", alguien preguntaba como emular el IF en ASM, y le dieron el siguiente ejemplo:

movfw   VAR
sublw  0x05
SKPNZ
call funcion

Osea si, VAR=5 va a FUNCION (IF VAR=5 va a FUNCION)

Es este IF simulado igual al que se escribe en esta MACRO ??? sobre la que pregunto !!!

Porque en lugar de dar ese ejemplo, de como simular IF con ASM...no le respondieron, a quien pregunto...PONE "IF" directamente y dejate de RLP (romper las pe_o__s), me explio, BRUNO !!!

Que otros comandos como el IF, reconoce el MPLAB ???

SALUDOS y ya puse medio alfajor en una cajita, con destino a Rosario, lo mando por Flecha Bus ???

Desconectado BrunoF

  • Administrador
  • DsPIC30
  • *******
  • Mensajes: 3865
Re: Sera ASM ???
« Respuesta #3 en: 17 de Marzo de 2007, 23:08:30 »
Antes que nada, poné los mates y las facturitas porque te puede llevar un ratito leer esto:

Bien, BRUNO, ya tengo una pista...ahora, entre tanta MACRO, como sabe el valor que debe tomar la demora...por ejemplo si en el programa, llamo a esta MACRO con DELAY 21, que valores toma ??? (aca parece que la demora sera de 21 us) pero como construye, esos 21 us ???

No hay que confundir lo que es una MACRO, con lo que es código puro.

Si pongo en mi programa antes del END:

      movlw 0x01

estaré ocupando 1 posición de memoria FLASH en el PIC.

Eso creo que está claro.

En lugar de lo anterior, podría poner en mi código esto:
 
PONER1ENW  MACRO
    movlw 0x01
ENDM

¿Cuánta memoria en el PIC ocupará eso?

Tal vez te sorprendas, pero no ocupará nada.
¿Por qué? Las MACROS sólo son utiles para generar código ASM variable(a veces no es variable), pero no ocupan por si mísmas memoria en el PIC ni generan código.

Ahora veamos cuándo ocupa memoria una "MACRO" en el PIC:

PONER1ENW  MACRO
    movlw 0x01
ENDM

     PONER1ENW

Aquí, al escribir PONER1ENW estoy haciendo referencia a mi MACRO. El ensamblador se fija qué hay dentro de la macro y reemplaza:

     PONER1ENW

por:

    movlw 0x01

por lo que escribir "PONER1ENW" ocupa 1 posicion de memoria en el PIC.



Muchas veces se usan para ejecutar un grupete de instrucciones que usas muy a menudo ya que resulta tedioso escribirlas una y otra vez.

Ejemplo:

En el programa cambio constantemente el puertob de salidas a entradas, segun corresponde.

Como lo cambio a ratos es mas facil poner asi:

PUERTOBENTRADA macro
    bsf     STATUS,RP0
    clrf     TRISB
    bcf     STATUS,RP0
endm

Y directamente en mi programa cada vez que quiero cambiar el puertob a entrada en lugar de escribir esas tres lineas, escribo directamente:

        PUERTOBENTRADA

y voilá. El ensamblador me remplaza "PUERTOBENTRADA" por las 3 lineas de codigo dentro de la macro correspondiente.

Entonces, la macro es un recurso de un poco más alto nivel de programación que nos ofrece el MPASM, para crear configuraciones y demás  cosas de manera mucho más simple, pero sus condiciones(los IF por ejemplo) solo se ejecutan ANTES de ensamblar el archivo y sirven para seleccionar qué porciones de codigo deben reemplazarse o no.



Ahora un ejemplo práctico para que lo veas más claramente:

SEMAFORO macro Valor ;Creo una macro, Valor indica que la MACRO recibe sólo un parámetro y lo llamo Valor.

 if(Valor < .80)       ;Si el parametro recibido es menor a 80...
   bsf   PORTA,0    ;Encender lampara Verde
   bcf   PORTA,1    ;Apagar lampara Amarilla
   bcf   PORTA,1    ;Apagar lampara Roja
 endif

 if(Valor >= .80) && (Valor < .160) ;Si el parametro recibido es igual o mayor a 80 Y menor a 160...
   bcf   PORTA,0                       ;Apagar lampara Verde
   bsf   PORTA,1                       ;Encender lampara Amarilla
   bcf   PORTA,1                       ;Apagar lampara Roja
 endif

 if(Valor > .160)                       ;Si el parametro recibido es mayor a 160...
   bcf   PORTA,0                      ;Apagar lampara Verde
   bcf   PORTA,1                      ;Apagar lampara Amarilla
   bsf   PORTA,2                      ;Encender lampara Roja
 endif

endm

     org 0x000        ;Vector de inicio de memoria FLASH del PIC.

     bsf  STATUS,RP0
     clrf TRISA          ;puertoA todo como salida
     bcf STATUS,RP0

     SEMAFORO 100

     end     

Cuando ensamblas esto, sucede lo siguiente:

El MPASM al detectar el "SEMAFORO 40" sabe que haces referencia a la MACRO de arriba. Entonces se fija el codigo que hay dentro de la macro y lo ejecuta como si se tratara de un lenguaje de programacion de alto nivel.

Comienza revisando el primer IF, el cual no se cumple.Ignora todo código dentro del IF.
Luego sigue con el segundo IF, que se cumple, entonces agrega en la posicion actual del programa ensamblado las lineas que estan dentro de este IF que se cumple,quedando como si tu originalmente hubieses puesto directamente:

     org 0x000

     bsf  STATUS,RP0
     clrf TRISA
     bcf STATUS,RP0

     bcf   PORTA,0
     bsf   PORTA,1
     bcf   PORTA,1

Luego sigue con el tercer IF, el cual tampoco se cumple. Lo ignora y termina la macro. Detecta el END, quedando en realidad esto:

     org 0x000

     bsf  STATUS,RP0
     clrf TRISA
     bcf STATUS,RP0

     bcf   PORTA,0
     bsf   PORTA,1
     bcf   PORTA,1

     end

Esto que te dije es para verlo de manera facil. Probablemente el MPASM vaya pasando a formato hexadecimal el codigo a medida que lo va produciendo pero lo puse asi para que lo veas mas facilmente.



Conclusion:

Las MACRO, DEFINE, etc no ocupan memoria en el PIC por el hecho de estar escritos dentro de un archivo a ensamblar.
Lo que puede generar y ocupar lineas de codigo es cuando utilizas esas MACRO, DEFINE, etc haciendo referencia/s a ella en el programa.

Saber usar bien las MACROS significa poder crear, por ejemplo un único programa compatible por ejemplo para 1 entre 5 modelos de PICs distintos, para 1 entre 20 tipos de pantallas LCD, etc etc etc.




Por otro lado, el MAPLAB, reconoce IF, como ASM???...pregunto esto por que en otro "hilo", alguien preguntaba como emular el IF en ASM, y le dieron el siguiente ejemplo:

movfw   VAR
sublw  0x05
SKPNZ
call funcion

Osea si, VAR=5 va a FUNCION (IF VAR=5 va a FUNCION)

Es este IF simulado igual al que se escribe en esta MACRO ??? sobre la que pregunto !!!

Porque en lugar de dar ese ejemplo, de como simular IF con ASM...no le respondieron, a quien pregunto...PONE "IF" directamente y dejate de RLP (romper las pe_o__s), me explio, BRUNO !!!

El IF se produce a la hora de ensamblar el codigo y sirve para que el ensamblador analice la condicion y en base a eso actue y genere tanto codigos como advertencias o incluso errores PERO NO SE EJECUTA NI EXISTE SIQUIERA JAMAS EN EL PIC.

La macro sirve principalmente solo para ahorrarse escribir rutinas repetidas o bien para que el ensamblador genere codigo asm distinto de salida analizando las condiciones,etc dentro de cada macro.

Los IFs en ASM deben hacerse, por ejemplo, de la forma que expusiste:

movfw   VAR
sublw  0x05
SKPNZ
call funcion

Aunque, hablando de Roma...SKPNZ es una MACRO! A diferencia de la que expusiste vos llamada DELAY, esta ya viene con el MPASM.

Escribir:

movfw   VAR
sublw  0x05
SKPNZ
call funcion

En realidad es lo mismo que escribir:

movfw   VAR
sublw  0x05
btfsc STATUS,Z
call funcion

No hay diferencia alguna, es sólo que escribir SKPNZ(Skip if No Zero) es mas fácil que recordar(tal vez  :mrgreen:) btfsc STATUS, Z.



Resumiendo, poner:

'Defino que Variable hace referencia a la posicion 0x20 de la RAM.
Variable EQU 0x20

 if(Variable == 0)
   call EsCero
 endif

NO significa que el ensamblador lo transforma al codigo asm correspondiente:

 movf Variable,F
 btfsc STATUS,Z
 call EsCero

El primero codigo es analizado como:

 if(0x20 == 0)
   call EsCero
 endif

por lo que no se cumple la condicion, y no agrega nada al asm "de salida".

Vos cuando me decis eso de ¿por qué no directamente ponen IF en el programa en lugar de todo ese codigo "feo"?

Sencillamente porque el MPASM no transforma el IF a instrucciones del PIC. Solamente revisa la condicion y actua en base a eso, pero solo en tu PC, y solo para generar el codigo asm final antes de ser ensamblado.

Lo que no impide que vos crees una MACRO que transforme el IF en codigo ASM, y de esta manera en lugar de poner todo ese codigo "feo" directamente pongas:

SIESMAYOR macro Nombre1 Nombre2
 movf Nombre1,W
 subwf Nombre2,W
 btfsc STATUS,C
endm


 SIESMAYOR PEPITO PEDRO

y el MPASM luego transforme eso a:

 movf PEPITO,W
 subwf PEDRO,W
 btfsc STATUS,C
   

Y si haces y haces rutinas para simplificarte la vida, te encontraras con que acabas de crear, prácticamente un nuevo compilador parecido a lo que podría ser el PIC BASIC PRO, el CCS, C18 o lo que fuere.
Fin.

Es bastante dificil explicar esto de las MACRO sin pizarrón y el aprendiz enfrente ;) . Si no quedó claro intento explicarme mejor.





Voy a hacer un pequeño apendice para explicar la diferencia entre una MACRO y una subrutina(funcion), y mi firme postura que definiré como:

"CASI SIEMPRE ES MUCHO MAS EFICIENTE UTILIZAR UNA SUBRUTINA EN LUGAR DE UNA MACRO"...

Supongamos que hago un programa, y necesito apagar y encender cuatro luces en un puerto:

Podria crear dos macros de la siguiente manera:

APAGAR macro
 bcf PORTB,0
 bcf PORTB,1
 bcf PORTB,2
 bcf PORTB,3
endm

ENCENDER macro
 bsf PORTB,0
 bsf PORTB,1
 bsf PORTB,2
 bsf PORTB,3
endm

y en el programa poner:

   ENCENDER
   call demora
   APAGAR
   call demora   
   ENCENDER
   call demora
   APAGAR
   call demora
   ENCENDER
   call demora
   APAGAR
   call demora   
   ENCENDER
   call demora
   APAGAR
   call demora

O podria haber hecho lo mismo creando dos subrutinas:

APAGAR bcf PORTB,0
           bcf PORTB,1
           bcf PORTB,2
           bcf PORTB,3
            return

ENCENDER bsf PORTB,0
               bsf PORTB,1
               bsf PORTB,2
               bsf PORTB,3
               return

Y en el codigo poner:

   call ENCENDER
   call demora
   call APAGAR
   call demora   
   call ENCENDER
   call demora
   call APAGAR
   call demora
   call ENCENDER
   call demora
   call APAGAR
   call demora   
   call ENCENDER
   call demora
   call APAGAR
   call demora

¿Cuál es la diferencia?

Bueno, usando MACROS, el asm que crea el MPASM antes de proceder al proceso de transformación en .hex es:

 bcf PORTB,0
 bcf PORTB,1
 bcf PORTB,2
 bcf PORTB,3

 call demora

 bsf PORTB,0
 bsf PORTB,1
 bsf PORTB,2
 bsf PORTB,3

 call demora

 bcf PORTB,0
 bcf PORTB,1
 bcf PORTB,2
 bcf PORTB,3

 call demora

 bsf PORTB,0
 bsf PORTB,1
 bsf PORTB,2
 bsf PORTB,3

 call demora

 bcf PORTB,0
 bcf PORTB,1
 bcf PORTB,2
 bcf PORTB,3

 call demora

 bsf PORTB,0
 bsf PORTB,1
 bsf PORTB,2
 bsf PORTB,3

 call demora

 bcf PORTB,0
 bcf PORTB,1
 bcf PORTB,2
 bcf PORTB,3

 call demora

 bsf PORTB,0
 bsf PORTB,1
 bsf PORTB,2
 bsf PORTB,3

 call demora

Mientras que usando las subrutinas el codigo generado no se agranda. Es el mismo que el expuesto anteriormente:

   call ENCENDER
   call demora
   call APAGAR
   call demora   
   call ENCENDER
   call demora
   call APAGAR
   call demora
   call ENCENDER
   call demora
   call APAGAR
   call demora   
   call ENCENDER
   call demora
   call APAGAR
   call demora

Usando macros, ese trozo de codigo ocupa 40 words en la FASH del PIC, mientras que usando subrutinas ocupa solo 16 words en la FLASH del PIC.

Entonces, la diferencia es que usando MACROS, muchas veces se desperdicia demasiada memoria FLASH del PIC en vano.



Que otros comandos como el IF, reconoce el MPLAB ???

Creo si mal no recuerdo que es el único que el MPASM acepta(en la actualidad).

SALUDOS y ya puse medio alfajor en una cajita, con destino a Rosario, lo mando por Flecha Bus ???

Jeje nooo por favor, que estoy a dieta.  :P
"All of the books in the world contain no more information than is broadcast as video in a single large American city in a single year. Not all bits have equal value."  -- Carl Sagan

Sólo responderé a mensajes personales, por asuntos personales. El resto de las consultas DEBEN ser escritas en el foro público. Gracias.

Desconectado Resistencio

  • PIC12
  • **
  • Mensajes: 82
Re: Sera ASM ???
« Respuesta #4 en: 18 de Marzo de 2007, 18:13:14 »
Espectacular, sorprendente, magistral, garcias BRUNO, entendi a la perfeccion esto de las MACROS, sus pro y sus contras...llevo poco tiempo en este FORO, y me sorprende gratamente, la molestia que te has tomado en escribirme, y explicar esto de las MACROS...(no digo explicarme, porque esta exposicion, tan detallada, sera patrimonio del FORO de ahora en mas).

En definitiva, el programa de donde saque esto...llama a esa MACRO, con:

DELAY 21 (a cual le da bolilla ??? - a las otras, ya entendi que las pasa de largo)

DELAY 28 (lo mismo !!!)

DELAY 48 (este es el mas raro)

DELAY 5 (esta parece la mas facil) creo que esta llamada ejecutara

if (Time==5)
        goto  $+1
        goto  $+1
        nop
        exitm
endif

Lo que no me "avivo", es como se resuelven las otras cuentas para que den 8 - 11 - 21 - 28 - 45 - 48  y estas llamadas, sí, estan hechas en el programa... ( quiero decir, no las puse yo, como ejemplos al azar...)

Ademas, se puede llamar a esta MACRO con otros valores, o solo se llama con los valores que puede atender ??? (segun lo que interprete en tu post, la respuesta es NO, pero confirmame, plz...)

En algun lado lei que estan disponibles, como el IF en las MACROS...los operandos, como los de tu ejemplo >, <, =, &, /...estare estudiando algo de eso y si me surgen dudas (casi con seguridad que asi pasara...) te estare consultando...tambien lei sobre THEN, ELSE, pero no estoy 100% seguro que tenga relacion con el ASM...

Hasta ahora en el RANKING del ALMACEN del ASM, mis posiciones son:

1º - DIOS
2º - BRUNO
3º - TODO LO DEMAS (sin ofender a nadie) tambien lei algo de CHARLY, que te pelea el puesto cuerpo a cuerpo !!!  :D

Como el "barba", no me contesta (anda con otros "kilombetes"), para mi sos el GURU del ALMACEN...Bueno BRUNO, me voy a sacar la segunda "pava" de la hornalla...Ahi tengo una ROSAMONTE DESPALADA, a estrenar...ahi te paso un amargo !!!

Hasta la proxima...GRACIAS !!! :)

DANIEL !!!

"Justo a mi, me toco ser YO" (creo que es de QUINO !!!) :-)
« Última modificación: 18 de Marzo de 2007, 18:17:55 por Resistencio »

Desconectado BrunoF

  • Administrador
  • DsPIC30
  • *******
  • Mensajes: 3865
Re: Sera ASM ???
« Respuesta #5 en: 18 de Marzo de 2007, 22:44:29 »
Y seguí con los mates nomás, hasta que quedes verde.  :D
Mis explicaciones son muchas veces muy extensas, porque me gusta ir pasito a pasito, "baby steps"



Espectacular, sorprendente, magistral, garcias BRUNO, entendi a la perfeccion esto de las MACROS, sus pro y sus contras...llevo poco tiempo en este FORO, y me sorprende gratamente, la molestia que te has tomado en escribirme, y explicar esto de las MACROS...(no digo explicarme, porque esta exposicion, tan detallada, sera patrimonio del FORO de ahora en mas).

En definitiva, el programa de donde saque esto...llama a esa MACRO, con:

DELAY 21 (a cual le da bolilla ??? - a las otras, ya entendi que las pasa de largo)

DELAY 28 (lo mismo !!!)

DELAY 48 (este es el mas raro)

DELAY 5 (esta parece la mas facil) creo que esta llamada ejecutara

if (Time==5)
        goto  $+1
        goto  $+1
        nop
        exitm
endif

Lo que no me "avivo", es como se resuelven las otras cuentas para que den 8 - 11 - 21 - 28 - 45 - 48  y estas llamadas, sí, estan hechas en el programa... ( quiero decir, no las puse yo, como ejemplos al azar...)




OK. Me fui tanto por las ramas que ovidé explicar lo que sucede con  DELAY 21...jeje

La MACRO que expones tal vez no es la más simple para comprender. Posee varias "cositas" bien calculadas que dificultan su compresiòn si no tenes bien claro el tema de los IF.

Fijate que la MACRO arranca primero comparando Time con 1, luego con 2, 3,4,5,6 y 7. Luego recién viene el otro conjunto de IFs que resolverán cualquier número entre 8 y 0(si. Digo 0 y no 255 porque en este caso poniendo 0 SUPONGO que obtenés el mayor tiempo de retardo posible: es decir, 256us @4Mhz).

¿Es esto casualidad? ¿Se podría invertir el orden de las comparaciones(IFs) y obtener el mísmo código asm de salida para cada valor de "Time"?

La respuesta es NO.

¿Por qué no?

Los casos cuando Time vale de 1 a 7 son fáciles. Los otros cuatro IFs son los que abarcan cualquier número. ¡Cualquiera! Inclusive del 1 al 7 también.

Como ya expliqué, el símbolo % signifíca en este lenguaje MOD. MOD es el resto de una división.
Si tengo por ejemplo: 1%4, entonces el resto de esa división es 1.
Si tengo:                 2%4, entonces el resto de esa división es 2.
Si tengo:                 3%4, entonces el resto de esa división es 3.
Si tengo:                 4%4, entonces el resto de esa división es 0.
Si tengo:                 5%4, entonces el resto de esa división es 1.
...                          ...

Entonces, generalizando: el resultado de hacer X%Y es siempre un valor entre 0 e (Y-1).

Como están contemplados dentro de esta MACRO los cuatro casos posibles de restos de una divisón por 4(nótese que se contemplan los casos para resto 0,1,2 y 3), esto significa que CUALQUIER valor de TIME satisfacerá uno y sólo uno de estos 4 casos de resto.
Ahora vamos con un ejemplo para ver la diferencia si invierto el orden de los IFs.
Hagamos primero el caso por ejemplo: DELAY 5
Si los dejo como los expones vos:

if (Time==1)...
if (Time==2)...
if (Time==3)...
if (Time==4)...
if (Time==5)...
if (Time==6)...
if (Time==7)...

if (Time%4==0)...
if (Time%4==1)...
if (Time%4==2)...
if (Time%4==3)...

Más allá de lo que se vaya a ejecutar dentro de la MACRO o no, podemos analizar a simple vista que el número 5 satisface dos Ifs:

Satisface tanto:

if (Time==5)...
como este:
if (Time%4==1)...

Entonces, fijate en la MACRO original y verás que al satisfacerse el if (Time==5) el MPASM agregará todo el código dentro del IF al archivo a ensamblar.
Pero aquí viene la línea crucial, y es que aparece dentro de IF, un endm (end macro). Esto hace que inmediatamente el MPASM salga de la MACRO, impidiendo que revise el resto de los otros IFs restantes.
¿Por qué? Porque el código necesario para crear un DELAY de 5US ya está dentro del if (Time==5). Si no saliera de la macro usando el endm, entonces también se cumpliría if (Time%4==1) produciendo más código y una demora errónea.

Entonces el código asm generado por la macro para DELAY 5 es:

goto  $+1
goto  $+1
nop

Lo que es correcto ya estas 3 líneas consumen 5 ciclos de ejecución, y a 4mhz son 5us.

Ahora, si los invierto:

if (Time%4==0)...
if (Time%4==1)...
if (Time%4==2)...
if (Time%4==3)...

if (Time==1)...
if (Time==2)...
if (Time==3)...
if (Time==4)...
if (Time==5)...
if (Time==6)...
if (Time==7)...

Se va a cumplir primero (Time%4==1)

Veámos qué hay dentro de este IF...:

movlw   (Time-5)/4
call        Delay_us
nop

Reemplacemos Time por 5 para obtener el verdadero código asm que ensamblará.

movlw   (5-5)/4
call        Delay_us
nop

Entonces, el asm resultante será:

movlw   0
call    Delay_us
nop

Lo que ya sería erróne. Esas líneas @ 4mhz por más rápida que sea la subrutina Delay_us, llevaría 6 ciclos de ejecución(1 del movlw + 2 del call + 2 del return + 1 del nop)
Fijate que también hay endm en estos IFs, por lo que el MPASM enseguida sale de la MACRO sin revisar los restantes, pero ya el error está cometido(aunque no he analizado la subrutina Delay_us para precisar en cuántos us).

Entonces, el orden de los IFs, en este caso, altera el resultado.Por eso están como están.

Vayamos ahora al caso del ya famoso: DELAY 21

PRIMERO OJO!!!!

DELAY 21 NO NECESARIAMENTE ES LO MISMO QUE DELAY .21!!!!

Por defecto el MPLAB trabaja en formato hexadecimal, por lo que si pones: DELAY 21, en realidad está haciendo DELAY .33 en sistema decimal!!!
Lo mísmo se aplica al resto de los casos. Yo voy a suponer que estamos hablando en sistema decimal. ¿Ok?

Ahora, ¿qué condición se cumple?

Se cumple sólo ésta:
if (Time%4==1)...

Ya que 21/4= 5 y resto 1. Y el resto es lo único que le interesa a la función MOD(%).

Entonces...vemos que en este caso el MPASM generaría esto:

movlw   (.21-5)/4
call        Delay_us
nop

Lo que finalmente sería:

movlw       4
call        Delay_us
nop

Oh casualidad! analicemos un poco. Necesito hacer 25us de retardo.
Veámos si mis premoniciones son verdaderas o falsas:


Tengo un movlw que ya me consume 1 ciclo, y tengo un call y un return que ya me consumen 4 ciclos más y luego un NOP que me consume 1 ciclo más.
En total sin contar lo que suceda o no dentro de la subrutina Delay_us, ya tengo seguro 6 ciclos(ya lo había mencionado arriba :D ).

Entonces el lo que sea que suceda entre que llamo al Delay_us y antes de que salga de él me debe llevar 15 ciclos de ejecución.

Veámos si entonces se cumple mi "premonición":

Delay_us          ADDLW  -1        ;precise delays used in I/O  (esto esta buenisimo de sumar -1)
                  btfss    STATUS,Z
                  goto    Delay_us
                  return


Dijiste: "esto esta buenisimo de sumar -1".
Esto exíste para simplificarte la vida. Lo que no quiere decir que efectivamente sume -1 ya que los negativos no existen "naturalmente" en estos microcontroladores.
Pero puedo decir que: ADDLW -1 es lo mísmo que decir ADDLW .255, es decir, 256- 1 ;) Esto debe ser precisamente lo que hace el MPASM. Es mucho más fácil cometer errores restando que sumando.

Veamos la subrutina:

W ingresa valiendo 4(véase anteriormente movlw 4)
Entonces voy a "estirar" todo el ciclo que genera esto:

Delay_us          ADDLW    .3        ;precise delays used in I/O  (esto esta buenisimo de sumar -1)
                  btfss    STATUS,Z
                  goto     Delay_us
Delay_us          ADDLW    .2        ;precise delays used in I/O  (esto esta buenisimo de sumar -1)
                  btfss    STATUS,Z
                  goto     Delay_us
Delay_us          ADDLW    .1        ;precise delays used in I/O  (esto esta buenisimo de sumar -1)
                  btfss    STATUS,Z
                  goto     Delay_us
Delay_us          ADDLW    .0        ;precise delays used in I/O  (esto esta buenisimo de sumar -1)
                  btfss    STATUS,Z
                  ;salta al return y sale.

Ahora sumo la cantidad de ciclos que lleva cada una(por dios! que de 15! :D :D )


Delay_us          ADDLW    .3        ;+1
                  btfss    STATUS,Z ;+1
                  goto     Delay_us ;+2
Delay_us          ADDLW    .2        ;+1
                  btfss    STATUS,Z ;+1
                  goto     Delay_us ;+2
Delay_us          ADDLW    .1        ;+1
                  btfss    STATUS,Z ;+1
                  goto     Delay_us ;+2
Delay_us          ADDLW    .0        ;+1
                  btfss    STATUS,Z ;+2
                  ;salta al return y sale.

Sumamos y da: 15!!!!!

Entonces en total tenemos: 6 ciclos + 15 = 21! Uau! lo hemos logrado! y con tan poquito código! qué bonito! ;)

Si miras sucederá de manera similar lo mísmo para los otros casos DELAY 8, DELAY 11, DELAY28, DELAY 45, DELAY 48.

¿Puedo expresar cuántos ciclos lleva la subrutina Delay_us en función de el valor con el que ingresa W?

Si.

Su función es:

Cantidad de ciclos de Delay_us = (W - 1) x 4 + 3

¿Bien?


Ahora, podría dedicarme a complicarte un poco el asunto, y unirte los cuatro caso de MOD en uno sólo que valga para todos haciendo:

DELAY macro Time
if (Time==1)...
if (Time==2)...
if (Time==3)...
if (Time==4)...
if (Time==5)...
if (Time==6)...
if (Time==7)...

movlw   (Time-4-Time%4)/4
call    Delay_us
if ((Time%4)%2==1)
   nop
endif

endm


Ese caso vale para generar el mísmo código que generan los 4 en la MACRO original. No es necesario que lo estudies, simplemente son manías mías ;)
Pero si decidís usarlo en reemplazo de los otros 4 casos, deberías obtener el mísmo código final.(Ensamblá el .asm con em MPLAB y andá a menú View --> Dissasembly Listing para ver qué código generó).

Espero que haya quedado claro.


Ademas, se puede llamar a esta MACRO con otros valores, o solo se llama con los valores que puede atender ??? (segun lo que interprete en tu post, la respuesta es NO, pero confirmame, plz...)

Se puede llamar con absolutamente cualquier valor natural entre 0 y 255.

En algun lado lei que estan disponibles, como el IF en las MACROS...los operandos, como los de tu ejemplo >, <, =, &, /...estare estudiando algo de eso y si me surgen dudas (casi con seguridad que asi pasara...) te estare consultando...tambien lei sobre THEN, ELSE, pero no estoy 100% seguro que tenga relacion con el ASM...

En el MPLAB ,anda a HELP -> Topics -> MPASM Assembler y buscá que ahí tenés explicado todo el potencial del MPASM que muchas veces es ignorado por completo por la gente que lo usa.


Hasta ahora en el RANKING del ALMACEN del ASM, mis posiciones son:

1º - DIOS
2º - BRUNO
3º - TODO LO DEMAS (sin ofender a nadie) tambien lei algo de CHARLY, que te pelea el puesto cuerpo a cuerpo !!!  lol

Como el "barba", no me contesta (anda con otros "kilombetes"), para mi sos el GURU del ALMACEN...Bueno BRUNO, me voy a sacar la segunda "pava" de la hornalla...Ahi tengo una ROSAMONTE DESPALADA, a estrenar...ahi te paso un amargo !!!

Jajaja no creo que haya rankings aquí. Todos aportamos lo que podemos en las áreas que más sabemos, y entre todos logramos formar este gigante, este coloso que es Todopic.

Al mate te lo acepto, pero dulce :) :)






Apéndice:

¿Qué pasa si pongo DELAY 0?
¿No generará demora alguna? ¿Generará 256 us¿ ¿O generará otra demora?

Analicemos:

Veremos que el único IF que se cumple para Time = 0 es:

if (Time%4==0)
   movlw       (Time-4)/4
        call        Delay_us
        exitm
endif

Entonces nos quedaría:

   movlw       (0-4)/4
        call        Delay_us
        exitm

Y oh! que pasa si hacemos 0-4?

Se produce un numero negativo -3. Pero los negativos no existen aqui!
Entonces...El MPASM transformarà el -3 en: 256 - 3.
Quedandonos: .253

Volvamos entonces a la macro:

   movlw       (.253)/4
        call        Delay_us
        exitm


Esa división no da como resultado un número entero. El MPASM elimina la parte decimal, de esta manera queda:

   movlw       .63
        call        Delay_us
        exitm

Ahora apliquemos la formulita que habia creado anteriormente:


Cantidad de ciclos de Delay_us = (W - 1) x 4 + 3 = (.63 - 1) x 4 + 3 = .251

Ahora, sumemosle 1 del movlw, 2 del call, y 2 mas del return:

= .251+ .5 = .256 us.

Ahora si puedo afirmar que el DELAY 0 es el mayor retardo posible y su duración es 256 us.

Tal vez decir DELAY 0 para implicar 256 us parece dificil de asociar.
Pues podrìas hacer DELAY .256 en su lugar y obtendrías exactamente el mísmo retardo(y de regalo te sale una advertencia del MPASM diciendo que se usarán sólo los bits menos significativos del .256 :D )


Ahora si. Fin.

Exitos.
"All of the books in the world contain no more information than is broadcast as video in a single large American city in a single year. Not all bits have equal value."  -- Carl Sagan

Sólo responderé a mensajes personales, por asuntos personales. El resto de las consultas DEBEN ser escritas en el foro público. Gracias.

Desconectado Resistencio

  • PIC12
  • **
  • Mensajes: 82
Re: Sera ASM ???
« Respuesta #6 en: 19 de Marzo de 2007, 01:09:08 »
BRUNO, esto es impecable...invalorable...estuve leyendo esta porcion de codigo hace semanas, hasta que descubri este FORO, y me lo arreglaste en 1 dia...la explicacion es "brillante" y no te hagas el "humilde"...si pude entenderlo yo, mas aun podran hacerlo los mas jovenes, que ahora se vienen "reload" de neuronas...

Tengo poco tiempo con los UC, y empece por casualidad, lo unico que conozco es el ASM, porque soy "fierrero" en electronica, y este lenguaje, me permite asociar facilmente los conceptos con los resultados...

Estuve considerando que usar estas MACROS, como alternativa frecuente, para el calculo de "demoras", es una solucion, elegante y facil para futuros programas...haciendo los calculos necesarios para otros "clock" de micro...Lo que me pregunto ahora, es porque no se estandariza este metodo, para todas las aplicaciones...muchos "foristas" encontrarian una solucion a los problemas de calcular demoras, ya que hay muchos que preguntan, sobre el tema !!!

Demas esta decirte que podes contar conmigo para lo que necesites desde aqui (BA - Capital)...No conozco tu especialidad, pero aveces la brecha comercial, entre nuestras ciudades, hace mas facil conseguir las cosas aqui...asi es que si necesitas algo, que se hace dificil conseguir alli, no tenes mas que avisarme...

No puedo decirte que podes preguntarme, sobre micros, ya que mis recursos son escasos, comparados con los tuyos...pero no solo de "micros" vive el hombre...

Aradezco una vez mas, tan desinteresado aporte, y te mando un abrazo, junto con un "azucarado" mate...HASTA LA PROXIMA !!! SALUDOS !!!

Lo del "ranking" es una broma, no dudo que aqui hay gente que como vos, sabe lo suficiente, para ocupar el TOP TEN !!!

================================
"Justo a mi, me toco ser YO" QUINO...

Desconectado BrunoF

  • Administrador
  • DsPIC30
  • *******
  • Mensajes: 3865
Re: Sera ASM ???
« Respuesta #7 en: 19 de Marzo de 2007, 10:17:12 »
BRUNO, esto es impecable...invalorable...estuve leyendo esta porcion de codigo hace semanas, hasta que descubri este FORO, y me lo arreglaste en 1 dia...la explicacion es "brillante" y no te hagas el "humilde"...si pude entenderlo yo, mas aun podran hacerlo los mas jovenes, que ahora se vienen "reload" de neuronas...

Tengo poco tiempo con los UC, y empece por casualidad, lo unico que conozco es el ASM, porque soy "fierrero" en electronica, y este lenguaje, me permite asociar facilmente los conceptos con los resultados...

Jeje...debo decirte que a mi parecer una gran parte de esta comunidad descubrimos los uC por casualidad.

Estuve considerando que usar estas MACROS, como alternativa frecuente, para el calculo de "demoras", es una solucion, elegante y facil para futuros programas...haciendo los calculos necesarios para otros "clock" de micro...Lo que me pregunto ahora, es porque no se estandariza este metodo, para todas las aplicaciones...muchos "foristas" encontrarian una solucion a los problemas de calcular demoras, ya que hay muchos que preguntan, sobre el tema !!!

Se podría estandarizar. Se podrían hacer conjuntos de algoritmos standart(y exísten muchas veces en los archivos .inc para asm).

Creo que no se ha masificado porque eso es justamente lo lindo del ASM: la libertad. El control al 100% de tu código. Tu optimización linea a linea del código, cosa que en otros lenguajes queda en manos más del compilador que del usuario programador.

Por supuesto que podes hacer un conjunto de rutinas para usar las demoras incluso a distintos Mhz.


Demas esta decirte que podes contar conmigo para lo que necesites desde aqui (BA - Capital)...No conozco tu especialidad, pero aveces la brecha comercial, entre nuestras ciudades, hace mas facil conseguir las cosas aqui...asi es que si necesitas algo, que se hace dificil conseguir alli, no tenes mas que avisarme...

No puedo decirte que podes preguntarme, sobre micros, ya que mis recursos son escasos, comparados con los tuyos...pero no solo de "micros" vive el hombre...

Te agradezco el ofrecimiento. Lo mejor que podes hacer es aportar vos al foro ayudando a otros en las áreas que sepas. :D

Mi especialidad es la informática, no la electrónica.

Venga ese mate, ahora si. ;)
Hasta pronto.

P.D. Muy linda la frase  jejeje



"All of the books in the world contain no more information than is broadcast as video in a single large American city in a single year. Not all bits have equal value."  -- Carl Sagan

Sólo responderé a mensajes personales, por asuntos personales. El resto de las consultas DEBEN ser escritas en el foro público. Gracias.

Desconectado Resistencio

  • PIC12
  • **
  • Mensajes: 82
Re: Sera ASM ???
« Respuesta #8 en: 20 de Marzo de 2007, 03:12:03 »
Hasta aqui, podria decirse que esto es como la biblia de las MACROS...estuve bajando unos TXT y lei mas sobre el tema...logicamente me cuesta asociar cuales "instrucciones" se interpretan en el programa principal y cuales en los "BLOCK"...

A simple vista y por lo que estuve viendo, hay varias directivas...lo que se refiere a las 32 instrucciones basicas, no tengo duda que seran interpretadas en el programa principal...pero la IF, por ejemplo se interpretan en los "block" o en MACROS (todo esto lo digo a riesgo de equivocarme !!! )

Aparecieron entonces otras condicionales como ELSE, WHILE, EXTERN, PAGESEL...he visto que PAGESEL o DT pueden ir sin problemas en el programa principal...pero no he visto que se usara ELSE o WHILE...

Tambien lei sobre operadores aritmeticos, como *, /, -, +, >>, <<, <, <, ==, !=, etc, etc, etc...ya he visto que el ==, %, ), (, se usan en el ejemplo de la MACRO que abre este "hilo"...pero no los demas (quizas porque no hacen falta en este ejemplo...

La pregunta es:

Suponiendo que tengo un REGISTRO EQU 0x15

Podria escribirse:

movwf  (registro * 2) - 1 , en el programa principal...estos operandos aritmeticos harian:

movwf (0x15 * 2) - 1 osea:

movwf (0x2A) - 1 osea:

movwf 0x29

En fin, tengo mas dudas que ADAN el dia de la madre...cuales se pueden usar, para que los interprete el compilador en el programa principal, y cuales se usan solo en BLOCKS...

Los resultados, producto de usar estos operandos, son para posiciones de memoria, (en el ejemplo de arriba, parece que el contenido de W se copia en la posicion 0x29, donde habra algun registro, predefinido ) o se pueden usar como resultados matematicos, para multiplicar o lo que sea, varios byte ???

po ej:

Se podria escribir

movlw   (reg1 * reg2) osea cargar a W con el resultado de esta multiplicacion ???

Quizas estoy preguntando una tremenda "bol__ez", ya que parece facil multiplicar asi en lugar de hacer RLF o sumas sucesivas !!!

No se si se trato este tema en algun otro lado, pero hice busquedad avanzada, en el ALMACEN ASM, y no encontre nada...me parecio que si hay algo en C...pero de C, noC...SALUDOS y gracias por leer !!!

_______________________________
"Justo a mi, me toco ser Yo" - QUINO


Desconectado BrunoF

  • Administrador
  • DsPIC30
  • *******
  • Mensajes: 3865
Re: Sera ASM ???
« Respuesta #9 en: 21 de Marzo de 2007, 00:42:08 »
Hasta aqui, podria decirse que esto es como la biblia de las MACROS...estuve bajando unos TXT y lei mas sobre el tema...logicamente me cuesta asociar cuales "instrucciones" se interpretan en el programa principal y cuales en los "BLOCK"...

A simple vista y por lo que estuve viendo, hay varias directivas...lo que se refiere a las 32 instrucciones basicas, no tengo duda que seran interpretadas en el programa principal...pero la IF, por ejemplo se interpretan en los "block" o en MACROS (todo esto lo digo a riesgo de equivocarme !!! )

Aparecieron entonces otras condicionales como ELSE, WHILE, EXTERN, PAGESEL...he visto que PAGESEL o DT pueden ir sin problemas en el programa principal...pero no he visto que se usara ELSE o WHILE...

Tambien lei sobre operadores aritmeticos, como *, /, -, +, >>, <<, <, <, ==, !=, etc, etc, etc...ya he visto que el ==, %, ), (, se usan en el ejemplo de la MACRO que abre este "hilo"...pero no los demas (quizas porque no hacen falta en este ejemplo...

En todo lenguaje de programación existe un conjunto de palabras reservadas.
Estas palabras al ser reservadas implican que sólo podrán ser usadas para ciertos fines, pero no para el resto. Ej. No puedo declarar una variable como "movlw" ya que movlw es una palabra reservada del MPASM y significa Move Literal to W.

No confundamos el set(o conjunto) de instrucciones del PIC,  con el set de instrucciones del MPASM.
El set de instrucciones del PIC dependerá de la familia del mísmo. A mayor familia, seguramente mayor cantidad(y complejidad) de instrucciones.
En cambio, el set de instrucciones del MPASM es muchísimo mas amplio que el set de instrucciones de cualquier PIC.
El MPASM posee un mayor conjunto de palabras reservadas para facilitar y posibilitar la programación de un microcontrolador PIC. Palabras como include, #define, macro, block,if, else, error,errorlevel,etc... son exclusívas para uso dentro del MPASM. Pero estas palabras ayudarán y posiblemente afectarán, tal vez, al archivo .hex final a generar que será cargado en el PIC.

El MPASM ofrece un abanico de instrucciones que tienen un espacio de influencia determinado:

Hay instrucciones como la "error" que sólo sirven para PROVOCAR un error en el proceso de ensamblado, para evitar que se genere un .hex con ciertos parámetro erróneos.

Hay otras(como los IF) que sólo se usan para que el MPASM ejecute la condición y en base a eso ejecute( o no) lo que hay dentro del IF. Un IF puede ir en cualquier lado del código. Escribir un IF en un archivo a ensamblar sólo tiene significado para el MPASM, no para el PIC.



Voy a intentar explicar el IF de una forma que tal vez resulte más fácil comprender.

Cuando envías a ensamblar un archivo, el MPASM comienza a recorrer linea a línea el código del archivo.
Si se topa con un IF, se fija si se cumple la condición. Si se cumple, entonces ingresa al IF y sigue ensamblando todo código que pudiese haber dentro. Si la condición no se cumple, se fija si existe "else". Si existe, ensambla todo código dentro de el. Si no existe el "else",  "salta" hasta el endif y esquiva(no ensambla) toda línea anterior a esa.

Ejemplo(familia 16F):

#DEFINE LIMPIAR .1

   org 0x000

   if (LIMPIAR == 1)
      clrf 0x03
   else
      messg "Recuerde: Es una mala costumbre no limpiar el registro STATUS al inicio del programa!"
   endif

Defino una variable limpiar con valor 1.
Fijémonos cómo se comportará el MPASM en este caso:
El MPASM encuentra primero el org 0x000. Eso le indica al MPASM que todo código ASM será grabado a partir de la  posición 0x0.

Luego se topa con el IF. aquí el MPASM revisa la condición y se pregunta: ¿Es LIMPIAR igual a 1?
Si la condición se cumple, el MPASM sigue leyendo lo que haya dentro de el IF, pero esquivará todo código que se encuentre en el else(si existiere).
Entonces se topa con clrf 0x03.
El MPASM reconoce la instrucción clrf. Sabe que es una de las 35 instrucciones que un PIC 16F tiene implementada, entonces a esta sí, la ensambla y prepara para el archivo .hex final.

¿Dónde la ubicará dentro de la memoria flash del PIC? Pues con la intrucción que pusimos arriba(ORG 0x000)
le pedimos que la ubicara comenzando desde la posicion 0x00.
Entonces, el MPASM creará el .hex de manera que la instrucción clrf 0xXX quede en la posición 0x00.
Como se cumplió la condición, esquiva todo lo que haya dentro del else, y busca el final del if(endif) y continúa ensamblando y no se detiene hasta no encontrar la directiva END.

Veamos ahora el caso en que no se cumple la condicion(copie todo el codigo, pero lo unico que cambia es el valor que le asigno a "LIMPIAR"):

#DEFINE LIMPIAR .0

   org 0x000

   if (LIMPIAR == 1)
      clrf 0x03
   else
      messg "Recuerde: Es una mala costumbre no limpiar el registro STATUS al inicio del programa!"
   endif

Aqui pasa lo mismo. Primero detecta el ORG ...y sabe que debe comenzar a ubicar toda instruccion que encuentre a partir de la posicion 0x00 de la FLASH.
Luego se hace la pregunta y en este caso no se cumple, por lo que busca el "else"(si es que existe.Si no existe directamente "salta" hasta el endif). Dentro del else hay una directiva que el MPASM reconoce: la messg. Esta directiva es sólamente útil para enviar un mensaje al MPLAB en la ventana "OUTPUT". Se usa para avisar de algo al usuario que ensambla el archivo, pero NO tiene nada que ver con las 35 instrucciones del PIC, por lo que no se ensambla ni genera código alguno en el .hex final.

¿Se comprendió?

La pregunta es:

Suponiendo que tengo un REGISTRO EQU 0x15

Podria escribirse:

movwf  (registro * 2) - 1 , en el programa principal...estos operandos aritmeticos harian:

movwf (0x15 * 2) - 1 osea:

movwf (0x2A) - 1 osea:

movwf 0x29

En fin, tengo mas dudas que ADAN el dia de la madre...cuales se pueden usar, para que los interprete el compilador en el programa principal, y cuales se usan solo en BLOCKS...

Efectivamente. Quedaría eso. Pero acá viene la parte que me parece te tiene confundido y este ejemplo va a servir para aclarartela.

Vos podés usar los operadores y directivas que el MPASM te ofrece, tal cual lo estás haciendo ahí pero el resultado ES UN MOVWF CC donde CC es una CONSTANTE. En este caso CC es 0x29. En el PIC sólo se graba la instruccion movlw referida a la posicion de memoria 0x29. ¡Nada de multiplicaciones o restas!

Entonces:

No creas que por hacer sumas. multiplicaciones,IFs realmente se van a "ensamblar" tal cual, es decir, conservando su función. El PIC admite sólo un determinado conjunto de instrucciones, y no puede salir de eso.

Si yo quisiese realmente que el PIC haga lo que querès tal cual lo pusiste ahí en código, tengo que usar el set de 35 instrucciones de esta familia:

W_TEMP  EQU 0x20
REGISTRO EQU 0x15

   movwf   W_TEMP   ;guardo el valor de W temporalmente en una variable W_TEMP
        movlw   0x15       ;W=0x15
        movwf   REGISTRO ;REGISTRO= W = 0x15
   bcf   STATUS,C  ;asegurar multiplicacion exacta por dos.
   rlf   REGISTRO,F   ;REGISTRO = REGISTRO * 2
        decf   REGISTRO,W   ;W = REGISTRO - 1
        movwf FSR                  ;Apuntar a la posicion de memoria a modificar:
        movf   W_TEMP,W      ;Recuperar valor original de W
   movwf   INDF      ;Y copiarlo en posicion de memoria correcta.


No pretendo que comprendas el código, ya que probablemente haya un par de cosas que son nuevas para vos. Ese código realmente tomaría el valor que contenga la variable REGISTRO, lo multiplicaria por 2, le restaria uno y copiaria el valor que tenia W en esa posicion de memoria resultante.
¿Podes apreciar la diferencia entre el simple(e invariable) movlw 0x29 que genera el uso de *,-,etc en el MPASM y el código que realmente haría que variara la posición de memoria en donde volcar W?

Entonces, hacé de cuenta que las directivas "adicionales" que te ofrece el MPASM pueden modificar el código asm, pero NO generan verdaderos IFs, ni verdaderas multiplicaciones, sumas,etc de manera que puedan ser interpretadas luego por el PIC mientras funciona, ¿ok?

Sería,simplificadamente(faltan muchos pasos, pero no nos interesan) un proceso asi:

Código original asm --> MPASM interpreta las directivas(IFs,MACROs,etc) y puede modificar/agregar código asm adicional --> se genera el código asm final --> MPASM ensambla código asm final --> archivo .hex generado listo para grabar en PIC.

Los resultados, producto de usar estos operandos, son para posiciones de memoria, (en el ejemplo de arriba, parece que el contenido de W se copia en la posicion 0x29, donde habra algun registro, predefinido ) o se pueden usar como resultados matematicos, para multiplicar o lo que sea, varios byte ???

por ej:

Se podria escribir

movlw   (reg1 * reg2) osea cargar a W con el resultado de esta multiplicacion ???

Quizas estoy preguntando una tremenda "bol__ez", ya que parece facil multiplicar asi en lugar de hacer RLF o sumas sucesivas !!!

Si leiste bien lo que dije anteriormente, deberias estar en condiciones de auto-responderte:

Si haces movlw (reg1 * reg2)  lo único que va a hacer el MPASM es fijarse cuánto vale en ese momento reg1 y reg2, multiplicarlos y hacer que quede finalmente movlw XX donde XX es el resultado de multiplicar reg1 * reg2

Ejemplo:

reg1 EQU 0x0C
reg2 EQU 0x0D

...

movlw (reg1 * reg2)

El MPASM transforma esto inmediatamente en:

movlw 0x9C

Por lo que termina siendo un valor constante. La multiplicacion existe sólo para el MPASM, pero desaparece para el PIC. Ok?

Para que el PIC pueda multiplicar realmente reg1 * reg2 y guardar ese resultado en W necesitas efectivamente un algoritmo que multiplique ambos usando sumas sucesivas,rotaciones o lo que sea.
Nada que ver una cosa con la otra, ¿no?.

Si vos lo que querés es programar fácil, usando IFs, multiplicaciones, divisiones, etc. Entonces, te recomiendo que mires el CCS(u otro), que es un compilador en lenguaje C para PICs, y en el cual sí podés poner directamente por ejemplo:

unsigned char reg1;
unsigned char reg2;
long resultado;

resultado = reg1*reg2;

y realmente transformar esa multiplicación en código asm que el PIC comprenda y pueda procesar durante su ejecución. Digamos que el CCS genera el codigo de esas "rotaciones" o "sumas sucesivas" automáticamente, necesarias para que el PIC sepa cómo multiplicar esos dos valores en cualquier momento.

Esa es la principal diferencia(hay muchas otras) entre un ENSAMBLADOR y un  COMPILADOR:

El ensamblado es mas bien una TRADUCCION del código original a codigo máquina.

El compilado es una verdadera TRANSFORMACION del código original a código asm, que luego será ensamblado para pasar a ser finalmente código máquina.

No se si se trato este tema en algun otro lado, pero hice busquedad avanzada, en el ALMACEN ASM, y no encontre nada...me parecio que si hay algo en C...pero de C, noC...SALUDOS y gracias por leer !!!

Es un tema bastante extenso, difícil de explicar por ahí si no tenes al menos experiencia con algun lenguaje de programación anteriormente.
La mayoría de las personas que trabajan con asm no usan cosas "raras". Nada de IFs, nada de operadores lógicos,etc. ya que la mayoría desconoce su existencia( y su increíble potencial si se utilizan inteligentemente).

Éxitos.
"All of the books in the world contain no more information than is broadcast as video in a single large American city in a single year. Not all bits have equal value."  -- Carl Sagan

Sólo responderé a mensajes personales, por asuntos personales. El resto de las consultas DEBEN ser escritas en el foro público. Gracias.

Desconectado Resistencio

  • PIC12
  • **
  • Mensajes: 82
Re: Sera ASM ???
« Respuesta #10 en: 21 de Marzo de 2007, 03:00:50 »
BRUNO, me estoy secando las lagrimas, lo entendi perfectamente...me parecia tan curioso que no se usaran estas instrucciones, no entendia la difrencia entre las que son del PIC y las del MPASM...de todos modos me parece un recurso interesante para ser explotado (pero me parece que hay que tener unas cuantas "horas de vuelo", por decirlo de algun modo, en programacion...)

Como supones, no tengo experencia con casi ningun lenguaje de programacion...digo casi ninguno, porque ya no cuento lo que aprendi en los ultimos años de colegio (me acuerdo que vi 2 horas de BASIC, para Z80, creo...yo, ensaye algo con el "debug" de mi primer XT, y eso si, varias horas de magnetrones y vavulas...lo que de alguna manera habla de mi edad... :D)

No tengo una rutina u orden para aprender sobre programacion, y entonces quizas este pegando saltos enormes...aun asi, pude entender lo que explicaste...lo dejare para mas adelante, si hiciera falta...ya que segun decis, quien elige este lenguaje, no acostumbra a manejar operandos aritmeticos o condicionales...

Lo unico que me quedaria por averiguar ahora, es cuales, afectan al .hex y cuales no...aunque por regla general, voy a desestimarlos para arrancar a programar algo y quizas mas adelante incorpore alguno...con los años me he convertido en "autodidacto" (palabra que tiene genero, apesar de que suene mal, y casi nadie la escriba asi) y con la increible posibilidad de internet (o de la internet), esta mania se ha reafirmado en mi...

A pesar de ello, me gustaria saber si podes recomendarme algun libro...ya que esto, sera mucho mas facil para vos, que contestarme a cada inquietud...digo esto porque no quiero abusar, se que esto demanda tiempo y concentracion...

Lamentablemente para los forista, segun estuve reflexionando, y dada mi condicion de "principiante", solo podran esperar de mi; preguntas, preguntas y mas preguntas...si bien es cierto que estoy leyendo hace casi 4 o 5 dias, todo el "almacen", hay algunas respuestas que no estan totalmente aclaradas, para mi apetito de aprendizaje, y me veo, penosamente obligado a preguntar...espero sepan disculpar tal atrevimiento, y aguardar, hasta que alguna vez sea Yo, quien pueda hacer algun aporte constructivo...

Quizas surgan nuevas dudas, tratare de encontrar las respuestas en algun lado del FORO, solo sino las encontrara, me animare a hacer alguna pregunta (aunque creo, que dado el excelente nivel manifiesto en el lugar, eso me cueste muchisimo, y quiera aprovecharlo, directamente con algun interlocutor... :-))

BRUNO, te agradezco infinitamente la molestia de responderme, con tanta claridad y urgencia...esto tiene para mi un valor incalculable, ya que son las primeras herramientas en el tema, esas que son en definitiva las fundamentales, para aprender bien...luego podre incurrir en miles de errores, pero sabre donde estan y como solucionarlos...y sino, siempre estaran ustedes para tenderme alguna mano... :mrgreen:

Entre tanto COLOMBIANO, PERUANO, ECUATORIANO, CHILENO, URUGUAYO, ESPAÑOLES, DOMINICANOS, etc, etc, etc (pase por el censo del FORO)...hasta me parece que estoy escribiendo como en las telenovelas...(en NEUTRO  :D :D :D)

Les mando un saludos a todos mis hermanos del FORO...Gracias por leer !!!

=================================================================

"Que otros se jacten de las páginas que han escrito; a mí me enorgullecen las que he leído." (J. L. B.)

=================================================================

_______________________________
"Justo a mi, me toco ser YO" - QUINO


Desconectado PalitroqueZ

  • Moderadores
  • DsPIC33
  • *****
  • Mensajes: 5474
    • Electrónica Didacta
Re: Sera ASM ???
« Respuesta #11 en: 21 de Marzo de 2007, 14:45:46 »
Bruno todavía no termino de leer tu explicación, pero te quedó impecable  :)
La propiedad privada es la mayor garantía de libertad.
Friedrich August von Hayek

Desconectado BrunoF

  • Administrador
  • DsPIC30
  • *******
  • Mensajes: 3865
Re: Sera ASM ???
« Respuesta #12 en: 22 de Marzo de 2007, 00:11:44 »
Gracias Pedrito ;)

Resistencio:(resistencia también tiene género y no lo sabía? :P )

Gracias por los halagos.
Te motivo a que busques en el foro, y si no encontrás respuesta a tus inquietudes, preguntes aquí en el foro ya que mucha gente podrá ayudarte.

Muchos me preguntan por un libro...realmente yo no tengo idea de libros en este tema. Al asm lo aprendí solito. Primero para la PC, luego en la Universidad y luego por casualidad para los PICs.

Te puedo sí recomendar que estudies hasta el hartazgo lo que significa un bit y un byte. Si no comprendés con plenitud su significado, imposíble comprender las instrucciones de un PIC.

Recién se me ocurrió una idea muy piola, tal vez me ponga y haga un librito de bolsillo sobre asm, como para tenerlo a mano cuando uno se está iniciando en ASM en este apasionante mundo de los PICs.

Saludos y nos escribimos ;)



"All of the books in the world contain no more information than is broadcast as video in a single large American city in a single year. Not all bits have equal value."  -- Carl Sagan

Sólo responderé a mensajes personales, por asuntos personales. El resto de las consultas DEBEN ser escritas en el foro público. Gracias.

Desconectado Resistencio

  • PIC12
  • **
  • Mensajes: 82
Re: Sera ASM ???
« Respuesta #13 en: 29 de Marzo de 2007, 05:25:31 »
Hola BRUNO, estuve leyendo atentamente tu explicacion...y puedo decir que la entiendo en un 90%...en realidad me tienen un poco confundidos algunos de tus ejemplos (estoy desestimando lo errores de tipeo, como los que estan en el ejemplo del semaforo...)

En tema viene a raiz de la preconceptualizacion que tengo, con respecto a lo que es un valor de registro y su posicion en memoria...

Por ejemplo...yo preguntaba por ahi si se podia hacer:

predefiniendo a "registro equ 0x15" (esto para mi es posicion de memoria, NO valor contenido en el registro)

movwf  (registro * 2) - 1 , en el programa principal...estos operandos aritmeticos harian:

movwf (0x15 * 2) - 1 osea:

movwf (0x2A) - 1 osea:

movwf 0x29

Entonces, esto para mi es como cargar el valor de W (aca no puse ninguno, pero podemos poner movlw 0xFF), y despues de la cuentita con los (*) y los (-), en la posicion de memoria 0X29, que deberia ocupar otro registro...

Quiza esto es un error conceptual mio, pero asi es como lo entendia...

En tu ejemplo, vos escribis:

=========================================================================

Si yo quisiese realmente que el PIC haga lo que querès tal cual lo pusiste ahí en código, tengo que usar el set de 35 instrucciones de esta familia:

W_TEMP  EQU 0x20
REGISTRO EQU 0x15

   movwf   W_TEMP   ;guardo el valor de W temporalmente en una variable W_TEMP
        movlw   0x15       ;W=0x15
        movwf   REGISTRO ;REGISTRO= W = 0x15
   bcf   STATUS,C  ;asegurar multiplicacion exacta por dos.
   rlf   REGISTRO,F   ;REGISTRO = REGISTRO * 2
        decf   REGISTRO,W   ;W = REGISTRO - 1
        movwf FSR                  ;Apuntar a la posicion de memoria a modificar:
        movf   W_TEMP,W      ;Recuperar valor original de W
   movwf   INDF      ;Y copiarlo en posicion de memoria correcta.

=============================================================================

Aca suponiendo que el valor de W que se carga en W_TEMP (sea 0XFF, como en mi ejemplo), lo que sigue es una cuenta que carga a REGISTRO (que esta en posicion 0x15 de RAM) con un valor ((0x15*2)-1)= 0x29, que al pasar a FSR, se convierte en posicion de memoria y cargara alli, el valor 0xFF que le precargue al reg. W_TEMP (que esta en posicion 0x20 de RAM)...un terrible despelote lo que escribi, pero leelo despacio, por favor !!! :-) :-) :-)

En definitiva es muy diferente a lo que puse Yo como ejemplo !!! :D

Lo que mas me confundio con este concepto, fue el ejemplo que dice:

===============================================================================

Ejemplo:

reg1 EQU 0x0C
reg2 EQU 0x0D

...

movlw (reg1 * reg2)

El MPASM transforma esto inmediatamente en:

movlw 0x9C

Aca parece que estoy cargando un valor literal 0x9C a W...NO ENTIENDO DE DONDE SALE ESTA CUENTA, como valor literal...

===========================================================================

Con todo esto, y en base a mis conceptos, para mi, es mas facil cargar el valor 0xFF en la posicion 0x29, con el primer metodo, es decir:

registro equ 0x15     ;declaro un registro llamado "registro" en posicion 0x15

movlw 0xFF  ; cargo a W con 0xFF

movwf  ((registro * 2) - 1) osea:

movwf ((0x15 * 2) - 1) osea:

movwf (0x2A) - 1 osea:

movwf 0x29 ; cargo 0xFF en posicion 0x29 (que es la posicion de algun registro, que no defini o declare, no se que termino se usa...)

==============================================================================

Bueno...BRUNO, como siempre...todo esto lo digo a riesgo de equivocarme...he invito a cualquiera que lea, a responder su punto de vista, y a indicarme posible errores...estoy arrancando con esto, asi que estoy a tiempo de modificar conceptos...GRACIAS POR LEER !!!

PDTA: podras explicar algun ejemplito con WHILE ??? POR FAVOR !!!


________________________________
"Justo a mi, me toco ser YO " QUINO.
« Última modificación: 29 de Marzo de 2007, 05:28:44 por Resistencio »

Desconectado BrunoF

  • Administrador
  • DsPIC30
  • *******
  • Mensajes: 3865
Re: Sera ASM ???
« Respuesta #14 en: 29 de Marzo de 2007, 11:19:04 »
Hola Resistencio.

Esos ejemplos fueron meramente demostrativos. Intenté aproximar su funcionamiento a lo más parecido posible. No te guíes por esos códigos. Eran sólo para que veas la diferencia claramente.
Obviamente es mucho más fácil hacer como decís, pero es porque ahora ya comprendés el tema.



El while...
Realmente no sé hasta dónde hay aplicación práctica del while. El while es un bucle, y como todo bucle, puede generar demasiadas líneas asm sin sentido. En fin:

Ejemplo:

una macro que rota un registro a la izq X veces:

ROTAIZQ macro Registro, Rotaciones
   if (Registro>0x6F)
      error El registro supera la posición máxima(0x6f)
      exitm
   endif
   variable i
i = 0
   while (i != Rotaciones)
      rlf Registro,F
i += 1
   endw
   endm


Y lo uso por ejemplo asi:

MiReg EQU 0x23

...
...
...

ROTAIZQ MiReg, 5    'roto a la izquierda MiReg 5 veces.

Si miramos al "Disassembly Listing" que genera el MPASM al llamar a la esa macro es:

0DA3     RLF 0x23, F                    XX:       ROTAIZQ MiReg,5
0DA3     RLF 0x23, F
0DA3     RLF 0x23, F
0DA3     RLF 0x23, F
0DA3     RLF 0x23, F

"i" es una variable. Fijate que justamente la declaré como variable. Es una variable AUXILIAR y es completamente ajena al PIC. Se usa sólo para poder realizar cálculos temporales auxiliares.

Espero haya quedado claro. Saludos.
"All of the books in the world contain no more information than is broadcast as video in a single large American city in a single year. Not all bits have equal value."  -- Carl Sagan

Sólo responderé a mensajes personales, por asuntos personales. El resto de las consultas DEBEN ser escritas en el foro público. Gracias.