Autor Tema: No iniciado en ensambler  (Leído 2066 veces)

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

Desconectado Berto

  • PIC16
  • ***
  • Mensajes: 191
No iniciado en ensambler
« en: 05 de Abril de 2016, 12:34:17 »
No se si estoy en lo cierto, pero por lo leido MPLAB esta relaccionado con ensambler.
Y concuerda porque mis proyectos creados asta ahora an funcionado sin instalar este.

Debido a que el "go to" puede crear problemas al saltar a otra linea de codigo
Tengo entendido que es mejor ensambler porque no solo realiza el salto reorganiza la pila como es debido

podrias ponerme un ejemplo de codigo??

Desconectado KILLERJC

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8242
Re:No iniciado en ensambler
« Respuesta #1 en: 05 de Abril de 2016, 13:27:36 »
Me parece que te estas confundiendo y mucho. En todo.

MPLAB es un IDE, un Entorno de desarrollo que el compilador (MPASM) base que trae es el de Assembler o mas corto ASM. Este mismo IDE puede usarse con otro compilador que es el de XC8.

Es decir no necesitas MPLAB para programar, si quisiera por ejemplo hacer un .c en el bloc de notas y luego escribir en la linea de comandos para compilarlo lo podria hacer, solo necesito el compilador.

ASM tiene una relacion directa de lenguaje maquina (opcode) a cada instruccion.

Citar
Debido a que el "go to" puede crear problemas al saltar a otra linea de codigo
Tengo entendido que es mejor ensambler porque no solo realiza el salto reorganiza la pila como es debido

No se a que te referis con pila.
En ASM vos sos el encargado de manejar la pila de hardware para los CALL/RETURN, el GOTO no realiza ningun guardado automatico, TODO pero TODO lo tenes que hacer vos. Por lo que se necesita un buen conocimiento del microcontrolador.
Si lo que te referis como "pila" es el stack, entonces estas equivocado, a no ser que vos implementes un stack, lo cual no creo que lo realizes, no vas a tener uno.

El GOTO en C es malo en el sentido que si lo traducis a ASM, vas a notar que nunca estas sacando los datos de la pila de llamada. Y aqui viene el como se implementa una funcion.

Normalmente en ASM es asi:

Código: ASM
  1. Principal:
  2.         CALL Funcion1
  3.         GOTO Principal         ; Esto es el while(1) en C, Loop infinito
  4.  
  5. Funcion1:
  6.         ;Aca instruccion
  7.         RETURN

Cuando estamos en Principal es decir el equivalente a nuestro while(1) llama a Funcion1, esta instruccion copia la direccion de la proxima instruccion ( GOTO Principal ) y lo guarda en la pila de llamadas, Luego carga el valor de Funcion1 ( su direccion ) en el Contador de Programa (lo que apunta que debe ejecutarse) que seria la primera instruccion de Funcion1, Al terminar Funcion1 te encontras con un RETURN, esa instruccion lo que hace es sacar esa direccion que se guardo con el CALL y ponerlo en el contador de programa..
Algo parecido ocurre por detras en C. Pero... que pasa si le pones un GOTO ?

Código: ASM
  1. Principal:
  2.         CALL Funcion1
  3.         GOTO Principal         ; Esto es el while(1) en C, Loop infinito
  4.  
  5. Funcion1:
  6.         ;Aca instruccion
  7.         GOTO Principal
  8.         RETURN

Aca el ejemplo, si miramos de nuevo estamos en Principal, se ejecuta el CALL, es decir se guarda la direccion y salta a Funcion1, Pero luego de ejecutarse la instruccion hay un GOTO en ves de un RETURN. El GOTO es un salto a la etiqueta Principal y no saca nada de esa pila, entonces nos quedo 1 lugar de la pila ocupado. Lo cual es un problema. Si esto se ejecuta otra ves la pila se va a ir llenando hasta que se llegue al ultimo lugar que tiene y comienze a sobreescribir ese ultimo valor. Esto puede llevar a que se ejecuten varias instrucciones de mas de forma no prevista, tambien puede llevar a que no funcione correctamente el programa.

En resumen, no se lo que leiste, pero si te vas a meter con ASM, vas a tener que leer el datasheet. Pero desde ya te digo que lo que dijiste esta mal.

--------------------------------------------------------

El GOTO es siempre malo ? - Respuesta : NO.
Muchas veces el GOTO puede salvar tiempo. pero siempre y cuando se haga dentro de la misma funcion.

Código: C
  1. void funcionc (void)
  2. {
  3.  
  4.         if( xxx )
  5.         {
  6.                 for(xx;x;xx)
  7.                 {
  8.                         if(cc)
  9.                         {
  10.                                 goto finalizar;
  11.                         }
  12.                 }
  13.         }
  14.  
  15.         if( y )
  16.         {
  17.                 for(xx;x;xx)
  18.                 {
  19.                         if(cyyc)
  20.                         {
  21.                                 goto finalizar;
  22.                         }
  23.                 }
  24.         }
  25.  
  26.  
  27. finalizar:
  28.  
  29.         xdsad = dsa;
  30.         ccsdadas++;
  31. }
« Última modificación: 05 de Abril de 2016, 13:32:17 por KILLERJC »

Desconectado Berto

  • PIC16
  • ***
  • Mensajes: 191
Re:No iniciado en ensambler
« Respuesta #2 en: 05 de Abril de 2016, 15:16:16 »
Con un 8085 solo me enseñaron a programar con ASM nemonicos me dijeron que eran ahora recuerdo el CALL Nunca daba problemas y al final estaba RET. Que seria return La pila es el stark seguro pero aqui habla de parametros padre y tine dos pares de salidas y entradas. La que conoci se dedicaba a sacar el ultimo dato que entraba es el que salia
asi era
20 - CALL etiqueta1 (pila-stak guarda siguiente linea=21 automaticamente yo no hacia nada)
21 -

40 - etiqueta1 (aqui podia aber cualquier cosa ejemplo MOV)
.......
.......
45-CALL etiqueta2(ahora el stak tiene al principio linea 41(la primera) y 21(la segunda))
.......
RET  (vuelve a linea 21)

100- CALL etiqueta2 ......
.......
.......
RET (vuelve a linea 41) ....principio stak vuelve a pasar a 21

Tambien se encargaba por si sola de mirar si debia o no atender al RET (banderas) ya que este podria ocurrir ocasionalmente sin 
el CALL adecuado o nisiquiera existir.

El problema de hacerlo esto desde C es que goto no tenga en cuenta esto

Una pregunta : ¿entonces incluso las void tienen un 2ºreturn-interno para volver a la posicion adecuada??
Si es asi es lo que quiero manipular

El salto no es para entrar en una funcion Lo contrario es para abandonarla El INT_EXT modifico valores con prioridad. No debe volver a la funcion porque esta remodifica los valores de forma perjudicial ya no validos. Preguntarle internamente a la funcion si INT_EXT modifico valores mediante int1 tambien lo es, puede segir cambiando algunos asta llegar a if(operoInterrupcion){ return 0 }, preguntarselo mas a menudo tampoco va a mejorar la cosa.

El problema en tu ejemplo es que el goto lo empleas de manera similar.

Luego a parte todas las funciones que creo son practicamente void no se que consecuencias puede tener pero me acomodo a que dentro de ella modifico todas las globales que quiera y en rara ocasion utilizo int8-16 funcion(). Pero si hay una ventaja que me gusta creo int1 funciones(), no es importante devolver 0 o 1 , la ventaja es que return x; abandona la funcion, de una forma mas segura que un Break; porque el Break; lo unico que haze en un momento dado es romper un bucle, para empeorar luego puede aver otro bucle. Return x; es magnifica para solucionar esto.

Desconectado KILLERJC

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8242
Re:No iniciado en ensambler
« Respuesta #3 en: 05 de Abril de 2016, 23:30:25 »
Exacto el PIC funciona de la misma forma, nomas que en ves de usar la RAM para tener esa pila, lo que hace es tener unos registros internos que no se pueden acceder.

En microprocesadores y microcontroladores un poco mas avanzados se usa el stack como pila, llamo a "stack" a donde C deja lugar para crear las variables locales,etc.

Te corrijo un error:
Citar
20 - CALL etiqueta1 (pila-stak guarda siguiente linea=21 automaticamente yo no hacia nada)
21 -

40 - etiqueta1 (aqui podia aber cualquier cosa ejemplo MOV)
.......
.......
45-CALL etiqueta2(ahora el stak tiene al principio linea 46(la primera) y 21(la segunda))
.......
RET  (vuelve a linea 21)

100- CALL etiqueta2 ......
.......
.......
RET (vuelve a linea 46)

En C lo podes hacer, hay que distinguir ahora 2 funciones, una es la de interrupcion y otra es una funcion comun.

Citar
Una pregunta : ¿entonces incluso las void tienen un 2ºreturn-interno para volver a la posicion adecuada??

No tiene un 2do return. basicamente si vieras el programa es algo asi:

Código: C
  1. void funcion(void)
  2. {
  3.        //Aca instruccion
  4. } //  <-- Este seria mi RETURN

Pero C no solamente ejecuta un RETURN al final de la funcion. Debe dejar el stack de la misma forma que estaba antes de entrar. Por lo cual esa ultima llave son varias instrucciones en ASM
Tambien podes hacer esto:

Código: C
  1. void funcion(void)
  2. {
  3.        if(x==0) { return; }       // <-- Esto no es un RETURN directo en ASM sino que tiene que hacer mas cosas por lo cual apuntara al final de esta funcion,
  4.  
  5. } //  <-- Este seria mi RETURN

Ahora en una interrupcion es distinto el tratamiento de esa funcion. Ya que ademas se le incorpora otras cosas como el devolver el contexto. Yo imagino que un return en una funcion de interrupcion deberia ejecutarlo correctamente. OJO no lo probe jamas.

Citar
El salto no es para entrar en una funcion Lo contrario es para abandonarla El INT_EXT modifico valores con prioridad. No debe volver a la funcion porque esta remodifica los valores de forma perjudicial ya no validos. Preguntarle internamente a la funcion si INT_EXT modifico valores mediante int1 tambien lo es, puede segir cambiando algunos asta llegar a if(operoInterrupcion){ return 0 }, preguntarselo mas a menudo tampoco va a mejorar la cosa.

Entonces dejame entenderte, lo que vos estas diciendo es que tenes un programa por ejemplo que modifica un array llamado MiArray[] , Pero cuando entra a la interrupcion INT_EXT vos modificas MiArray[] con los valores que vos queres pero queres que cuando vuelva la otra funcion no los siga modificando ?

Si es asi la unica forma que le veo es desactivar las interrupcion INT_EXT en ese momento, sino no podrias jamas tener la certeza suficiente de entre justo antes de una asignacion.

Desconectado Berto

  • PIC16
  • ***
  • Mensajes: 191
Re:No iniciado en ensambler
« Respuesta #4 en: 06 de Abril de 2016, 18:37:38 »
se puede utilizar un return; sin mas en void funcion();
es resultado similar return x; en int1 funcion();????

Respecto a lo ultimo todo lo contrario, Es la funcion corriente la que se deberia anular INT EXT tiene prioridad sobre estas funciones
un MASTER pasa continuamente informes a 2 SLAVE mismos pic, parecidos programas, hago pruebas no se cual es mejor o peor
El problema es cuando uno de los SLAVE interfiere en uno de los informes, el normalmente MASTER deja de serlo por un instante para poder leer, al contrario que los otros 2 solo lee un int8 y pone una dx=1 y sale enseguida de esta.
Esto puede solo suponer modificar una variable, pero si se elimina informe[3] se debe reordenar [4] a [3] problematico si el imforma asta array[10] o mas

if(sx){ see(XX); }//sx=TRUE micro-sensor fue interrumpido para atender INT_EXT impazto ALIEN=XX
esto if(sx) esta por todas partesgo Seria mas  limpio librarse de ellas

porque algo como hacer avanzar puede hacerlo con un informe eliminado, en momento innadecuado
for(cx=0;nu>cx;cx++){
v8=psz[cx];
//v16=dis[v8];
  if(rti<1){//AVANZAN
if(dis[v8]>vsp){ //if(distancia > vsp=velozcidad_inicial+1)
dis[v8]-=vel[v8];//se le hace avanzar
}else{
dis[v8]=1;//1 distancia minima
}
  } else {//RETROCEDEN
  dis[v8]+=vel[v8];//el sensor ya no los detedta a una distancia superior a 830
  if(dis[v8]>830){  output_high(PIN_A2);  nu--;//SENSOR ocupado no puedra atender INT EXT     tiketa = "Sokp"
if(dos){
  output_low(PIN_A0); delay_us(50);  re1(); delay_us(50); output_high(PIN_A0); delay_us(50); re2(); RX=0;//
   }//primordial pasar informe a los 2 lo antes posible independiente del valor
else { if(V1){  re1(); } else { re2(); } }//primordial pasar informe
output_low(PIN_A2); //SENSOR desocupado puede atender INT EXT
} }  //cuando rtirada sea if(rti<1){ volveran a aparecer y avanzar }
if(sx){ see(XX); }//sx=TRUE micro-sensor fue interrumpido para atender INT_EXT impazto ALIEN=XX
}//for(cx) 

Esto tanbien debo hacerlo en otras funciones con return; haciendo que todo sea mas pesado

Las funciones que interfiern detras de INT EXT son estas: puede ser un instante o durar mucho, si hay que reordenar

Código: [Seleccionar]
void see(unsigned int8 AX){//Se interrumpio sensor-RW para leer impazto en XX
res[AX]--;
if(res[AX]<1){
output_high(PIN_A2); //SENSOR ocupado no puedra atender INT EXT     tiketa = "Sokp"
elimina(AX); output_low(PIN_A2); }//redundancia 2
else { dis[AX]+=retro; if(lesi){ if(vel[AX]>1){  vel[AX]=(vel[AX]*9)/10; } } }//lesi=herir x cada impacto recivido se le quita un 10% d velozcidad...
sx=0;//se atendio a interrupcion INT EXT
di++;
}
void elimina(int8 ali){ 
if(psz[0]==ali || psz[1]==ali){//se trata del objetivos principales
printf(lcd_putc1,"\fDESTROY<%u> ",ali);//destroy_psz[0]
if(nu>1){ if(psz[0]==ali){ pasa(1); } else { pasa(2); } } else { nu=0; }//RW2();  }//posicion-distancia[1]...[0] [2]...[1] [3]...[2] asta que lu diga nu
lxl=14; //delay_ms(250);
} else {//lo + raro no era el objetivo-prioritarios
printf(lcd_putc1,"\fSECUNDARIO<%u>FUERA ",ali);//destroy_psz[1]a[nu]
for(c4=2;nu>c4;c4++){
if(psz[c4]==ali){ pasa(c4+1); break; } }   
lxl=22;//lx+=20;
}
//lcd_putc1("pas1  ");
//LO PRIMERO enviarles la posicion eliminada sea cual sea lo antes posible para que la reseten HAY DATOS K NO SE COMUNICAN como numero de impactos total V1+V2
if(dos){
  output_low(PIN_A0); delay_us(50);  re1(); delay_us(50); output_high(PIN_A0); delay_us(50); re2(); delay_us(50);//con esto refrescan el array donde el eliminado ya no existe
  output_low(PIN_A0);  delay_us(50); resRW(ali);//V1 resetea impactos=0 posicion[alien] y prepara A0=1 para RW V2
  output_high(PIN_A0); delay_us(50); resRW(ali); RX=0;//V2 resetea impactos=0 posicion[alien] y prepara el prosimo refresco para que actue en RW V1
  }//primordial pasar informe a los 2 lo antes posible independiente del valor int1 vez
else { if(V1){  re1(); delay_us(50); resRW(ali); } else { re2(); delay_us(50); resRW(ali); } }//primordial pasar informe
output_low(PIN_A2); //SENSOR desocupado puede atender INT EXT
hz=1;//No debe aplicarse de new RW2 ya se realizo tanto re1(); como re2();
//lcd_putc1("paso 2 ");  lcd_gotoxy(20,4);
//printf(lcd_putc2," F%u R1.%u R2.%u [%u-%u] ",Fallo[0],Fallo[1],Fallo[2],Fallo[3],Fallo[4]); //Solo el numero de fallos RS");
lcd_putc2("\f");
ms=7;
de++;//otro objetivo derribado
}
///(3 23[200]  (4  55[666]  ---->  3 55[
void pasa(int8 d){
int8 ii,aa;//=0;
for(ii=d;nu>ii;ii++){///posicion-distancia[1]->[0]....[2]->[1]....[3]->[2]....sucesivo asta total de nu
aa=ii-1;
v8=psz[ii];
//if(v8>205){ break; }
v16=dis[v8];
psz[aa]=v8;//p[0]=p[1]
dis[v8]=v16;
}
nu--;
}
void resRW(int8 al){
output_high(PIN_A3); //RW TRUE  debe estar ya selecionado V I o V II  A0=0 o A0=1
  spi_write(21); PM();  spi_write(al); PM();//nu=21 esto resetea a 0 el numero de inpactos en la posicion[ali]
  output_low(PIN_A3); //RW FALSE
 delay_us(50);
}

Desconectado Berto

  • PIC16
  • ***
  • Mensajes: 191
Re:No iniciado en ensambler
« Respuesta #5 en: 06 de Abril de 2016, 19:03:59 »
output_high(PIN_A2);  //SENSOR ocupado no puedra atender INT EXT
output_low(PIN_A2); //desocupado

cuando manda un nuevo refresco informes a los normalmente SLAVE en vez de utilizar disable porque es algo que se repite constantemente influllen directamente animacion

Desconectado KILLERJC

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8242
Re:No iniciado en ensambler
« Respuesta #6 en: 06 de Abril de 2016, 21:50:21 »
Si vas a compartir una variable con una interrupcion tenes que tener seguridad que nunca va a ocurrir, como te decia, lo mejor es que desactives la interrupcion de INT_EXT y preguntes por si la flag esta en 1, de ser asi salis y activas las interrupcion para que entre y vuelva a modificar todo.

//Aca desactivo interrupcion
desactivo_interrupcion(INT_EXT);
for(cx=0;nu>cx;cx++)
{
           if ( flag INT_EXT == 1 ) break;   // Aca if preguntando por la flag
}
activo_interrupcion(INT_EXT);

Asi en cada vuelta, en caso de existir una interrupcion a la cual NO va a entrar por que esta desactivada el if lo va a detectar, va a salir de ese for, vas a activar la recepcion, con lo cual va a entrar a la interrupcion y comenzar a tomar los datos.

La otra que se me ocurre es Crear otro array que se use en el main ( MisegundoArray) y al final luego de todo el for, y con las interrupciones deshabiltadas preguntar si es que se habia entrado a INT_EXT, de haber entrado entonces no hago nada, si no entro entonces podes copiar MisegundoArray a MiPrimerArray ( el que usa tambien la interrupcion )

Desconectado Berto

  • PIC16
  • ***
  • Mensajes: 191
Re:No iniciado en ensambler
« Respuesta #7 en: 07 de Abril de 2016, 20:40:11 »
Valla esto se a salido de ASM y ahora estoy liado con el timer
pero solo aclarar una cosa anular int_ext no seria bueno esta ligada directamente a SPI
Solo puede haber comunicacion entre dos de manera actual
PIN_A2=1 les dice a los SLAVE-1-2 que no pueden escribir porque esta ocupado el MASTER-0 estos segiran haciendo otras funciones pero principalmente preparados para pasar a Master lo antes posible nada mas que A2=0 entonces en MASTER-0 podra actuar int_ext pasandolo a slave en un periodo muy corto un solo int8 "sujeto XX alcanzado"

Tambien sirbe para impedir que -normalmenteSLAVE-1-pase a Master porque normalmenteSLAVE-2 esta ocupando el puerto SPI escribiendo en normalenteMASTER-0

Si solo anulo int_ext no impide que los normalmeteSLAVE-1-2 pasen a Master en momento inadecuado


 

anything