본문 바로가기
코스웨어/13년 스마트컨트롤러

9월 24일 ATmega 시리얼 통신 & 어셈블리 정리

by 알 수 없는 사용자 2013. 9. 24.
728x90
반응형


추가된 함수와 변수

 typedef struct _cmdmap

{
  void *vpCmd;
  void (*fp)(void);
} CMDMAP;
/* 문자열을 받을 수 있는 보이드 포인터와 함수포인터를 멤버로 가지는 구조체 변수 */

CMDMAP stCMDList[] = {
            { "LED ON"  , LED_on },
            { "LED OFF"  , LED_off },
            { "LCD"    , LCD_test   },
            { "ADC"    , ADC_test   },
            { 0      , 0     }
          };
//-------------------CMDMAP 구조체의 함수 포인터와 같은 형태의 함수들---------------------------------
void LED_on()
{
  PORTA = 0;  // LOW : H-L  켜짐

  return;
}

void LED_off()
{
  PORTA = 0xFF;  // HIGH : H-H  꺼짐

  return;
}

void LCD_test()
{
  LCD_string("LCD Testing...");
}

void ADC_test()
{
  unsigned int uiRet;
  unsigned char ucString[] = "0000";
  
  uiRet = Sensor_Light();
  
  ucString[0= (uiRet / 1000) + '0';  // 만자리 추출
  ucString[1= ((uiRet % 1000)/100) + '0';
  ucString[2= ((uiRet % 100)/10) + '0';
  ucString[3= (uiRet % 10) + '0';

  UART_string("ADC Light Sensor : ");
  UART_string_ln(ucString);
}
//-------------------CMDMAP 구조체의 함수 포인터와 같은 형태의 함수들---------------------------------


// USART Rx Complete 인터럽트

void __vector_25(void)
{  
  static unsigned char ucBuf[31];
  static unsigned char ucCnt = 0;
    
  //menu();

  ucBuf[ucCnt] = UDR0;
  if ('z' >= ucBuf[ucCnt])
  {
    if ('a' <= ucBuf[ucCnt])
    {
      ucBuf[ucCnt] = ucBuf[ucCnt] - 32;  // 소문자 -> 대문자로
    }
  }
  

  // '\n' '\r' 순서로 옴
  if ('\r' == ucBuf[ucCnt])
  {
    ucBuf[ucCnt] = 0;  // 개행문자 -> 널문자로
    
  }
  else  // 개행문자가 없을 시 종료
  {
    ucCnt++;
    if (ucCnt == 30)  // 버퍼가 다 찼을 때
    {
      ucBuf[ucCnt] = 0;
    }
    else
    {
      return;
    }
  }

  cmd(ucBuf);
  ucCnt = 0;
  //UART_string_ln("");    // 한 칸 띄워줌
  
  return;
}

/* 하이퍼 터미널로 입력된 문자열과 CMDMAP 구조체 배열 stCMDList의 문자열을 비교하여

해당하는 함수를 호출 해주는 역할을 하는 함수 */
void cmd(void *vpCmd)
{
  CMDMAP *stpCmd = stCMDList;

  while(1)
  {
    if(0 == stpCmd->fp)
    {
      break;
    }
    if(0 == my_strcmp(vpCmd, stpCmd->vpCmd))
    {
      (stpCmd->fp)();    // 명령어가 일치하면 해당 함수 실행
      break;
    }
    ++stpCmd;
  }
  
  return;
}



 무한루프를 출력하는 어셈블리 소스

.386

.MODEL FLAT


PUBLIC _STST

PUBLIC _LDST


.CODE

_STST PROC NEAR32

PUSH    EBP

MOV     EBP, ESP

PUSHFD ; EFL 임시저장  

  

MOV     EAX, [EBP-4] ; EFL이 변형되기 때문에 

AND     EAX, 0FFFFFEFFH ; TF(Trap Flag) 제거

MOV     [EBP-4], EAX 

  

MOV     ESP, [EBP+8] ; ESP를 _EAX 위치로 이동

ADD     ESP,  40


PUSHAD ; 레지스터 값들 push

PUSH [EBP+4] ; push EIP(return address)

PUSH [EBP-4] ; push EFL

  

ADD ESP,  24 ; _ESP  위치로 가서

MOV EAX, EBP

ADD EAX, 8 ; EBP로 부터 ESP를 찾아서  

PUSH EAX ; old ESP-4 push

  

PUSH [EBP] ; old EBP push


MOV ESP, EBP                ; Exit code

POP EBP

RET


_STST ENDP


; 메모리 정보를 cpu 레지스터로 이동

_LDST PROC NEAR32


MOV ESP, [ESP+4] ; ESP = &CONTEXT

POPFD ; EFL CPU로 : EFL = CONTEXT.EFL

POP EAX ; EIP BACK UP : OLD EIP 

MOV EBX, ESP ; TEMP = CURRENT ESP

MOV ESP, [ESP+12] ; ESP = OLD ESP

PUSH EAX ; RETURN ADDR 조작(EIP) : SAVE OLD EIP

MOV ESP, EBX ; ESP = CURRENT ESP


POP EDI

POP ESI

POP EBP


ADD ESP, 4 ; skip ESP


POP EBX

POP EDX

POP ECX

POP EAX


MOV ESP, [ESP-20] ; RETURN ADDR 지정

SUB ESP, 4


RET


_LDST ENDP

 




 위의 어셈블리 함수를 호출하여 사용하는 c언어 소스

 

#include <stdio.h>


typedef struct _context

{

int efl;

int eip;

int edi;

int esi;

int ebp;

int esp;

int ebx;

int edx;

int ecx;

int eax;

}CONTEXT;


void print_reg(CONTEXT *stpReg);

void STST(CONTEXT *);

void LDST(CONTEXT *);


int main(void)

{

CONTEXT stReg = {0,};


printf("************************ Before ***************************\n");

print_reg(&stReg);


STST(&stReg);

printf("************************ After ****************************\n");

print_reg(&stReg);


getchar();

LDST(&stReg);

printf("Kernel Panic\n");

return 0;

}


void print_reg(CONTEXT *stpReg)

{

printf("EAX      VALUE : 0x%08X\tECX      VALUE : 0x%08X\n", stpReg->eax, stpReg->ecx);

printf("EDX      VALUE : 0x%08X\tEBX      VALUE : 0x%08X\n", stpReg->edx, stpReg->ebx);

printf("ESP ADDR VALUE : 0x%08X\tEBP ADDR VALUE : 0x%08X\n", stpReg->esp, stpReg->ebp);

printf("ESI ADDR VALUE : 0x%08X\tEDI ADDR VALUE : 0x%08X\n", stpReg->esi, stpReg->edi);

printf("EIP ADDR VALUE : 0x%08X\tEFL ADDR VALUE : 0x%08X\n\n", stpReg->eip, stpReg->efl);

}



728x90