Ir ao conteúdo
  • Cadastre-se
Vicente Cesar

Passando código de C para assembly

Recommended Posts

Como estou aprendendo assembly resolvi fazer todos meus códigos em assembly para treinar e deixa-los mais rápidos. Porém, como não tenho muita experiencia estou tendo algumas dificuldades. Alguns erros consegui identificar mas não consegui corrigi-los, então queria saber se poderiam me orientar.

 

OBS1: o código se trata da comunicação de uma manete de playstation 2 com o pic (O código em C funciona perfeitamente, apenas o em assembly se encontra com problemas. Fonte do código em C : Robotizando.com)

 

Observação2: Não é por preguiça que estou pedindo ajuda, já estou no terceiro dia agarrado nesse código, acho que é mais pela minha falta de experiencia.

 
Primeiro, os problemas que identifiquei.
 
"PRINCIPAL ;GOTO PRINCIPAL para voltar a esse ponto do programa
 
CALL LER_CONTROLE
BTFSC BEYTE2,2
CALL L_STATUS
BTFSS BEYTE2,2
CALL L_ERRO
GOTO PRINCIPAL
 
 
L_STATUS
BSF LED_STATUS
BCF LED_ERRO
RETURN
L_ERRO
BCF LED_STATUS
BSF LED_ERRO
RETURN"
 
Chamei de led_status o led que acende quando um botão da manete é pressionado e led_erro o led que acende quando nada é pressionado. O depurador mostra que o código funciona, mas ao testar o codigo no Microcontrolador, apenas o led_status acendia, independente do que eu apertasse. (Aparentemente esta apresentando comportamento contrário ao que foi programado, pois o led_erro deveria acender quando nada fosse apertado).
O BEYTE2,2 é onde esta salvo o valor 1 ou zero para o botão L1, se zero não foi pressionado se 1, foi pressionado.
 
BCF BEYTE6,CONT_BIT ; Zero
 
Cont_bit é um contador que conta de 0 a 7, o objetivo era gravar cada bit da variável Beyte6, porém apenas o bit 2 esta sendo alterado, independente do valor do contador (Vi isso através do depurado do MPLAB).
 
Como o código em C funcionou, acho que o problema não seja no hardware.
 
Agora os códigos completos:
 
Em C:
 

 
//-----------------------------------------------------
// CONTROLE PLAYSTATION
// Essa biblioteca possui funções para ler o estado do controle
// de playstation
//
// Alterações em: 
//
// 01/04/2007 23:30 - Preparação da versão 1.0 - somente funcionalidades básicas
// 05/12/2007 02:45 - versão 1.0 - primeira versão funcional
// 14/01/2009 01:10 - Adição de descrição de sinais
//-----------------------------------------------------
 
//-----------------------------------------------------
// Descritivo das cores da fiação do controle PS
// Clock    = Azul
// Data     = Marrom - Atenção! Esse sinal precisa de Pull Up (1K)
// Command  = Laranja
// Att      = Amarelo
// Vcc      = Vermelho
// Gnd      = Preto
// Force Feed Back = Cinza (não implementado ainda)
//-----------------------------------------------------
 
//Pinos onde o controle está conectado
#define cmd  PIN_B7
#define att  PIN_B6
#define clk  PIN_B5
#define dado PIN_B4
 
//Tempos em micro-segundos (us)
#define tempoInicio     40
#define tempoClk        40
#define tempoEntreByte  40
#define tempoEntreCiclo 20 //ms
 
int psxDado[6];      //Buffer do controle
int psxDadoAnt[6];  //Buffer do controle
int1 psxMudou;
 
//Botões do Controle
int1 btnSelect = 0;
int1 btnJoyE  = 0;
int1 btnJoyD  = 0;
int1 btnStart = 0;
int1 btnUp    = 0;
int1 btnDown  = 0;
int1 btnLeft  = 0;
int1 btnRight = 0;
 
int1 btnL1 = 0;
int1 btnL2 = 0;
int1 btnR1 = 0;
int1 btnR2 = 0;
int1 btnTriangulo = 0;
int1 btnBola      = 0;
int1 btnQuadrado  = 0;
int1 btnXis       = 0;
 
int X_Left=0;
int Y_Left=0;
int X_Right=0;
int Y_Right=0;
 
int centro_x_right = 0;
int centro_y_right = 0;
int centro_x_left = 0;
int centro_y_left = 0;
 
int psxCont;       //contador genérico
 
// ----------------------------------------------------
//   psxLeByte - Captura um byte, enviado pelo controle através do pino DADO
// ----------------------------------------------------
int psxLeByte()
{
   int aux=0;
   int c;
 
      for(c=0;c<=7;c++) //Passa por todos os bits da variável psxByte
   {
      output_bit(clk,false); //baixa o clock, isso faz com que o controle disponibilize o dado no pino "dado"
      delay_us(tempoClk);   
 
      //invertido para representar a realidade do controle
      if(INPUT(dado)==1)
         bit_clear(aux, c);
      else
         bit_set(aux, c);
 
      output_bit(clk,true); //Sobe o clock
   }
 
   delay_us(tempoEntreByte);
   return (aux);   
}
 
// ----------------------------------------------------
//   psxGravaByte - Escreve um byte, enviado pelo controle através do pino CMD
// ----------------------------------------------------
void psxGravaByte(int byteDado)
{
   int c;
   for(c=0;c<=7;c++) //Passa por todos os bits da variável psxByte
   {
       //Sobe ou desce o pino de acordo com cada bit da variável psByte
       //significa que estamos enviando o comando 0x01h para o controle
      if(bit_test(byteDado,c))
         output_bit(cmd,true); 
      else
         output_bit(cmd,false);         
 
      output_bit(clk,false);   //depois de setar o pino, manda clock para o controle
      delay_us(tempoClk);      //aguarda um tempinho...
      output_bit(clk,true);   //sobe clock... NOTA: clock sensível a borda de descida
   }
 
   output_bit(cmd,true);      //sobe comando para sinalizar
   delay_us(tempoEntreByte);    //espera um tempinho entre um byte e outro
}
 
 
// ---------------------------------------------------------------------------
//   psxCopiaDado - copia buffer atual para anterior
// ---------------------------------------------------------------------------
void psxCopiaDado()
{
   int i;
   for(i=0;i<6;i++)
      psxDadoAnt = psxDado;
}
 
// ---------------------------------------------------------------------------
//   psxComparaDado - Compara leitura anterior com a atual
// ---------------------------------------------------------------------------
boolean psxComparaDado()
{
   int j;
   for(j=0;j<6;j++)
   {
      if(psxDadoAnt[j]!=psxDado[j])
         return (1);
   }
   return (0);
}
 
 
// ---------------------------------------------------------------------------
//   psxAtualizaVariaveis - converte buffer de leitura para variaveis discretas
// ---------------------------------------------------------------------------
void psxAtualizaVariaveis()
{
   if((psxDado[0] & 1) == 1)
      btnSelect = 1;
   else
      btnSelect = 0;
 
   if((psxDado[0] & 2) == 2)
      btnJoyE = 1;
   else
      btnJoyE = 0;
 
   if((psxDado[0] & 4) == 4)
      btnJoyD = 1;
   else
      btnJoyD = 0;
 
   if((psxDado[0] & 8) == 8)
      btnStart = 1;
   else
      btnStart = 0;
 
   if((psxDado[0] & 16) == 16)
      btnUp    = 1;
   else
      btnUp    = 0;
 
   if((psxDado[0] & 32) == 32)
      btnRight = 1;
   else
      btnRight = 0;
 
   if((psxDado[0] & 64) == 64)
      btnDown  = 1;
   else
      btnDown  = 0;
 
   
   if((psxDado[0] & 128) == 128)
      btnLeft  = 1;
   else
      btnLeft  = 0;
 
 
   
   if((psxDado[1] & 1) == 1)
      btnL2 = 1;
   else
      btnL2 = 0;
 
   if((psxDado[1] & 2) == 2)
      btnR2 = 1;
   else
      btnR2 = 0;
 
   if((psxDado[1] & 4) == 4)
      btnL1 = 1;
   else
      btnL1 = 0;
 
   if((psxDado[1] & 8) == 8)
      btnR1 = 1;
   else
      btnR1 = 0;
 
   if((psxDado[1] & 16) == 16)
      btnTriangulo = 1;
   else
      btnTriangulo = 0;
 
   if((psxDado[1] & 32) == 32)
      btnQuadrado  = 1;
   else
      btnQuadrado  = 0;
 
   if((psxDado[1] & 64) == 64)
      btnXis = 1; 
   else
      btnXis = 0;
 
   if((psxDado[1] & 128) == 128)
      btnBola = 1;
   else
      btnBola = 0;
 
   x_right = psxDado[2];
   y_right = psxDado[3];
   x_Left = psxDado[4];
   y_Left = psxDado[5];
}
 
 
// ----------------------------------------------------
//   psxLeControle - Executa a leitura do controle de playstation
// ----------------------------------------------------
void psxLeControle()
{
   int psxByte = 0;
 
   output_bit(cmd,true);   //sobe comando
   output_bit(clk,true);   //sobe clock
   output_bit(att,false);   //att em low - habilita o joystick
   delay_us(tempoInicio);   //aguarda o controle entender o att em low
 
   //Envia o primeiro byte para o controle - 0x01
   psxByte = 1;         
   psxGravaByte(psxByte);
 
   //Envia o segundo byte para o controle - 0x42h
   psxByte = 66;
   psxGravaByte(psxByte);
 
   //Envia o terceiro byte para o controle - 0x00
   psxByte = 0;
   psxGravaByte(psxByte);
 
   //Recupera os 6 próximo bytes
      for(psxCont=0; psxCont<6; psxCont++)
         psxDado[psxCont] = psxLeByte();
 
   //Volta o att para alto... libera o controle indicando que ele pode parar de enviar dados
   output_bit(att,true);   
 
   //Compara com a variável anterior e verifica se será 
   //necessário atualizar as variaveis discretas
   if(psxComparaDado()==1)
   {
      psxAtualizaVariaveis();
      psxMudou = true;
   }
   else
      psxMudou = false;
 
   psxCopiaDado();
 
}
 
 
 
 
 
 
 
 
Minha versão em assembly:
 

#INCLUDE <P16F628A.INC>
 
__CONFIG _HS_OSC & _WDT_OFF & _PWRTE_ON & _MCLRE_OFF & _BOREN_OFF & _LVP_OFF & _CP_OFF & DATA_CP_OFF
 
;Paginação de mesmoria
 
#DEFINE BANCO_0 BCF STATUS,RP0 ; BCF deixa um bit igual a 0
#DEFINE BANCO_1 BSF STATUS,RP0 ; BSF deixa um bit igual a 1
 
#DEFINE LED_STATUS PORTA,2 ;Led associado ao Port A Pino 0
#DEFINE LED_ERRO PORTA,3 ;Led associado ao Port A Pino 0
#DEFINE _DATA PORTB,4
#DEFINE _CLOCK PORTB,5
#DEFINE _ATT PORTB,6
#DEFINE _CMD PORTB,7
CBLOCK 0X20                    ; Endereço inicial da memoria do banco a ser usada
 
  BYTE_DADO
  CONT
  CONT_BIT
  C_US
  BEYTE1
  BEYTE2
  BEYTE3
  BEYTE4
  BEYTE5
  BEYTE6
 
ENDC
 
ORG 0X00 ;Onde a proxima proxima instrução sera gravada
GOTO INICIO ;Devia para inicio
 
ORG 0x04
RETFIE ;Se ocorrer alguma interrupção, o programa retona onde ouve a interrupção
 
INICIO ; 1 - Entrada 0 - Saida
 
BANCO_1
MOVLW B'11110011'
MOVWF TRISA
MOVLW B'00011111'
MOVWF TRISB
 
BANCO_0
MOVLW B'00000111'
MOVWF CMCON
 
MOVLW B'00000000'
MOVWF CONT_BIT
 
MOVLW B'00000000'
MOVWF BYTE_DADO
 
 
 
MOVLW B'00000000'
MOVWF PORTA
MOVLW B'00000000'
MOVWF PORTB
 
MOVLW B'00000000'
MOVWF BEYTE1
MOVLW B'00000000'
MOVWF BEYTE2
MOVLW B'00000000'
MOVWF BEYTE3
MOVLW B'00000000'
MOVWF BEYTE4
MOVLW B'00000000'
MOVWF BEYTE5
MOVLW B'00000000'
MOVWF BEYTE6
 
PRINCIPAL ;GOTO PRINCIPAL para voltar a esse ponto do programa
 
CALL LER_CONTROLE
BTFSC BEYTE2,2
CALL L_STATUS
BTFSS BEYTE2,2
CALL L_ERRO
GOTO PRINCIPAL
 
 
L_STATUS
BSF LED_STATUS
BCF LED_ERRO
RETURN
L_ERRO
BCF LED_STATUS
BSF LED_ERRO
RETURN
GRAVAR_BEYTE
MOVLW B'00001001'
MOVWF CONT
MOVLW B'00000000'
MOVWF CONT_BIT
RETORNO_GRAVAR_BIT
DECFSZ CONT
GOTO GRAVAR_BIT
BSF _CMD
MOVLW .38
CALL TIMER
RETURN
 
GRAVAR_BIT
BTFSS BYTE_DADO,CONT_BIT ;SE == 1 Pula linha abaixo
BCF _CMD ; Zero
BTFSC BYTE_DADO,CONT_BIT ;SE == 0 Pula linha abaixo
BSF _CMD ; Um
BCF _CLOCK
MOVLW .38
CALL TIMER
BSF _CLOCK
MOVLW B'00000001'
ADDWF CONT_BIT
GOTO RETORNO_GRAVAR_BIT
 
 
LER_BYTE
MOVLW B'00001001'
MOVWF CONT
MOVLW B'00000000'
MOVWF CONT_BIT
RETORNO_LER_BIT
DECFSZ CONT
GOTO LER_BIT
    MOVLW .38
CALL TIMER
RETURN
;BCF Zera um bit
 
LER_BIT
BCF _CLOCK
MOVLW .38
CALL TIMER
BTFSS _DATA ;SE == 1 Pula linha abaixo
BCF BEYTE6,CONT_BIT ; Zero
BTFSC _DATA ;SE == 0 Pula linha abaixo
BSF BEYTE6,CONT_BIT ; Um
    BSF _CLOCK
MOVLW B'00000001'
ADDWF CONT_BIT
GOTO RETORNO_LER_BIT
 
LER_CONTROLE
 
BSF _CMD
BSF _CLOCK
BCF _ATT
MOVLW .38
CALL TIMER
 
    MOVLW .1
MOVWF BYTE_DADO
CALL GRAVAR_BEYTE
 
MOVLW .66
MOVWF BYTE_DADO
CALL GRAVAR_BEYTE
 
MOVLW .0
MOVWF BYTE_DADO
CALL GRAVAR_BEYTE
   
CALL LER_BYTE
MOVFW BEYTE6
MOVWF BEYTE1
 
CALL LER_BYTE
MOVFW BEYTE6
MOVWF BEYTE2
 
CALL LER_BYTE
MOVFW BEYTE6
MOVWF BEYTE3
 
CALL LER_BYTE
MOVFW BEYTE6
MOVWF BEYTE4
 
CALL LER_BYTE
MOVFW BEYTE6
MOVWF BEYTE5
 
CALL LER_BYTE
 
BSF _ATT  
RETURN
 
 
TIMER
NOP
MOVWF C_US
DECFSZ C_US
GOTO $-1
RETURN
 
END

Compartilhar este post


Link para o post
Compartilhar em outros sites

Se estás a aprender ASM talvez devias começar com algo mais simples. Creio que o teu compilador é o CCS. Se for, há uma opção nele que "converte" o codigo em C e mostra em ASM. Vai â aba "compile" e dê um click em "C/ASM List".

Compartilhar este post


Link para o post
Compartilhar em outros sites

Crie uma conta ou entre para comentar

Você precisar ser um membro para fazer um comentário

Criar uma conta

Crie uma nova conta em nossa comunidade. É fácil!

Crie uma nova conta

Entrar

Já tem uma conta? Faça o login.

Entrar agora





Sobre o Clube do Hardware

No ar desde 1996, o Clube do Hardware é uma das maiores, mais antigas e mais respeitadas publicações sobre tecnologia do Brasil. Leia mais

Direitos autorais

Não permitimos a cópia ou reprodução do conteúdo do nosso site, fórum, newsletters e redes sociais, mesmo citando-se a fonte. Leia mais

×