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

20151007 - 권오민 - GPIO&AFIO / ASSEMBLY(C와 링크하기)

by 알 수 없는 사용자 2015. 10. 7.
728x90
반응형

ARM-Cortex

GPIO & AFIO

General-purpose and alternate-function I/Os

(GPIOand AFIOs) - P.159

GPIO functional description






open-drain




http://terms.naver.com/entry.nhn?docId=755118&cid=42341&categoryId=42341


http://irmus.tistory.com/76


GPIO functional description(continue)





GPIO 실습

- 목표 : 스위치를 눌렀을 때는 Main보드에 LED만 켜지고 땠을 때는 Core보드에 LED만 켜져 있어야 한다.





- 소스

#define  GPIOA_CRL    (*(volatile unsigned int *)0x40010800)
#define  GPIOA_IDR    (*(volatile unsigned int *)0x40010808)
#define  GPIOA_ODR    (*(volatile unsigned int *)0x4001080C)
#define  GPIOA_BRR    (*(volatile unsigned int *)0x40010814)
#define  GPIOA_BSRR    (*(volatile unsigned int *)0x40010810)
#define  RCC_APB2ENR    (*(volatile unsigned int *)0x40021018)
  
#define  GPIOC_CRH    (*(volatile unsigned int *)0x40011004)
#define  GPIOC_IDR    (*(volatile unsigned int *)0x40011008)
#define  GPIOC_ODR    (*(volatile unsigned int *)0x4001100C)
#define  GPIOC_BRR    (*(volatile unsigned int *)0x40011014)
#define  GPIOC_BSRR    (*(volatile unsigned int *)0x40011010)

int main(void)
{
  RCC_APB2ENR    |= 0x14;    //C:0001, A:1000이므로 14를 or한다.
  GPIOA_CRL    = 0x44444441;
  GPIOC_CRH    = 0x44414444;
  
  while(1)
  {
    if(!(GPIOA_IDR &0x04))    //Switch가 On되어 있다면,
    {
      GPIOA_BSRR  = 0x01;  //Core LED를 켠다.
      GPIOC_BRR  = 0x1000;  //Main LED를 끈다

    }
    else            //Switch가 Off되어 있다면,
    {
      GPIOA_BRR  = 0x01;  //Core LED를 끈다.
      GPIOC_BSRR  = 0x1000;  //Main LED를 켠다.

    }
  }
  
  return 0;
}





●결과






ASSEMBLY

CASSEMBLY 링크

함수인자 포인터로 받기

- main.c

#include <stdio.h>

void smart(int *);

int main(void)
{
  int iNum = 100;

  smart(&iNum);

  printf("%d\n", iNum);

  return 0;
}


- smart.asm

.386
.MODEL FLAT

PUBLIC  _smart

.CODE
  _smart  PROC  NEAR32
    push  ebp
    mov  ebp,  esp

    mov  eax,  [ebp + 8]
    mov  DWORD PTR[eax],  777


    mov  esp,  ebp
    pop  ebp
    ret
  _smart  ENDP

END




함수인자 구조체로 받기

- 어셈블리의 경우 stack이 밑에부터 쌓이므로 인자의 값을 순서대로 넣어야한다.

- 문제 : 다음 구조체 안에 인자 A, B, C, D1, 2, 3, 4asm를 통해 입력하라.


#include <stdio.h>

typedef struct _common
{
  int A;
  int B;
  int C;
  int D;
}common;

void smart(common *);

int main(void)
{
  common obj;

  smart(&obj);

  printf("A = %d\n", obj.A);
  printf("B = %d\n", obj.B);
  printf("C = %d\n", obj.C);
  printf("D = %d\n", obj.D);

  return 0;
}


- 정답 : smart.asm

.386
.MODEL FLAT

PUBLIC  _smart

.CODE
  _smart  PROC  NEAR32
    push  ebp
    mov  ebp,  esp

    mov  eax,  [ebp + 8]
    mov  DWORD PTR[eax],  1
    mov  DWORD PTR[eax+4],  2
    mov  DWORD PTR[eax+8],  3
    mov  DWORD PTR[eax+12],  4

    
    

    mov  esp,  ebp
    pop  ebp
    ret
  _smart  ENDP

END



- 결과



어셈블리와 변수

- 어셈블리는 변수라는 개념이 없다.

- 우리가 변수라고 생각하는 것이 주어지면 그것만큼의 공간을 확보할 뿐이다.

    - 예제





레지스터 값들 출력하기1

- main.c

#include <stdio.h>

typedef struct _common
{
  unsigned int eax;
  unsigned int ebx;
  unsigned int ecx;
  unsigned int edx;
  unsigned int esi;
  unsigned int edi;
  unsigned int esp;
  unsigned int eip;
  unsigned int efl;

}common;

void smart(common *);

int main(void)
{
  common obj;

  smart(&obj);

  printf("eax : [%08x]\n", obj.eax);
  printf("ebx : [%08x]\n", obj.ebx);
  printf("ecx : [%08x]\n", obj.ecx);
  printf("edx : [%08x]\n", obj.edx);
  printf("esi : [%08x]\n", obj.ecx);
  printf("edi : [%08x]\n", obj.edx);
  printf("esp : [%08x]\n", obj.esi);
  printf("eip : [%08x]\n", obj.edi);
  printf("efl : [%08x]\n", obj.esp);

  return 0;
}

- smart.asm


.386
.MODEL FLAT

PUBLIC  _smart

.CODE
  _smart  PROC  NEAR32
    push  ebp
    mov  ebp,  esp

    mov  eax,  [ebp + 8]
    mov  DWORD PTR[eax],    eax
    mov  DWORD PTR[eax+4],  ebx  
    mov  DWORD PTR[eax+8],  ecx
    mov  DWORD PTR[eax+12],  edx
    mov  DWORD PTR[eax+16],  esi
    mov  DWORD PTR[eax+20],  edi
    mov  DWORD PTR[eax+24],  esp

    push  ebx
    mov  ebx,    [ebp+4]
    mov  [eax+28],  ebx
    pop  ebx

    pushfd
    push  ebx
    mov  ebx,    [ebp-4]
    mov  [ebp+32],  ebx
    pop  ebx

    
    mov  esp,  ebp
    pop  ebp
    ret
  _smart  ENDP

END




레지스터 값들 출력하기2

- 어셈블리 함수가 호출되기 직전에 상태의 값을 출력하게 수정하려고 한다.

- eax도 이미 값이 수정 되어버렸다.

 

- esp의 위치를 조정한다.

    - 구조체의 위치를 바꾼다.


- main.c

#include <stdio.h>

typedef struct _common
{
  unsigned int esp;
  unsigned int eip;
  unsigned int ebp;
  unsigned int edi;
  unsigned int esi;
  unsigned int edx;
  unsigned int ecx;
  unsigned int ebx;
  unsigned int eax;
  unsigned int efl;
}common;

void smart(common *);

int main(void)
{
  common obj;

  smart(&obj);

  printf("main : [%08x]\n", main);
  printf("&obj : [%08x]\n"&obj);

  printf("eax : [%08x]\n", obj.eax);
  printf("ebx : [%08x]\n", obj.ebx);
  printf("ecx : [%08x]\n", obj.ecx);
  printf("edx : [%08x]\n", obj.edx);
  printf("esi : [%08x]\n", obj.esi);
  printf("edi : [%08x]\n", obj.edi);
  printf("esp : [%08x]\n", obj.esp);
  printf("eip : [%08x]\n", obj.eip);
  printf("efl : [%08x]\n", obj.efl);
  printf("ebp : [%08x]\n", obj.ebp);

  return 0;
}

- smart.asm

.386
.MODEL FLAT

PUBLIC  _smart

.CODE
  _smart  PROC  NEAR32
    push  ebp
    mov  ebp,  esp

    mov  esp,  [ebp+8]  ;esp가 eax와 동일하다.
    add  esp,  40  ;변수만큼 내린다.
    pushfd
    push  eax  ;당장 eip를 구하기 까다롭기
    push  ebx  ;때문에 구조체의 순서를 바꾼다.
    push  ecx
    push  edx
    push  esi
    push  edi
    push  [ebp]  ;ebp
    push  [ebp+4]  ;eip

    mov  esp,  ebp  ;해결이 불가하여, 원래의 stack로 돌아온다.
    push  eax
    mov  eax,    ebp
    add  eax,    12
    mov  esp,  [ebp+8]
    mov  [esp],  eax
    mov  esp,  ebp
    sub  esp,  4
    pop  eax


    mov  esp,  ebp
    pop  ebp
    ret
  _smart  ENDP

END













728x90