◉GPIO & AFIO
●General-purpose and alternate-function I/Os
(GPIOs and AFIOs) - P.159
●GPIO functional description
![](https://t1.daumcdn.net/cfile/tistory/27076F4D5614B84915)
![](https://t1.daumcdn.net/cfile/tistory/277C654D5614B84B20)
![](https://t1.daumcdn.net/cfile/tistory/2174EB4D5614B84C28)
●open-drain
![](https://t1.daumcdn.net/cfile/tistory/264E0F485614B95606)
http://terms.naver.com/entry.nhn?docId=755118&cid=42341&categoryId=42341
http://irmus.tistory.com/76
●GPIO functional description(continue)
![](https://t1.daumcdn.net/cfile/tistory/266D904E5614B96A16)
![](https://t1.daumcdn.net/cfile/tistory/275A0E4E5614B96C2A)
●GPIO 실습
- 목표 : 스위치를 눌렀을 때는 Main보드에 LED만 켜지고 땠을 때는 Core보드에 LED만 켜져 있어야 한다.
![](https://t1.daumcdn.net/cfile/tistory/2119ED4B5614B97F0B)
- 소스
#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; } |
![](https://t1.daumcdn.net/cfile/tistory/275216485614B98C03)
●결과
◉C와 ASSEMBLY 링크
●함수인자 포인터로 받기
- 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
|
![](https://t1.daumcdn.net/cfile/tistory/26127F475614B67C19)
![](https://t1.daumcdn.net/cfile/tistory/240F44475614B6C21E)
●함수인자 구조체로 받기
- 어셈블리의 경우 stack이 밑에부터 쌓이므로 인자의 값을 순서대로 넣어야한다.
- 문제 : 다음 구조체 안에 인자 A, B, C, D에 1, 2, 3, 4를 asm를 통해 입력하라.
#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; } |
![](https://t1.daumcdn.net/cfile/tistory/26041B475614B67E28)
- 정답 : 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
|
![](https://t1.daumcdn.net/cfile/tistory/240A92475614B67F20)
- 결과
![](https://t1.daumcdn.net/cfile/tistory/241203475614B68019)
![](https://t1.daumcdn.net/cfile/tistory/2366694E5614B80116)
●어셈블리와 변수
- 어셈블리는 변수라는 개념이 없다.
- 우리가 변수라고 생각하는 것이 주어지면 그것만큼의 공간을 확보할 뿐이다.
- 예제
![](https://t1.daumcdn.net/cfile/tistory/250E46475614B99B2B)
![](https://t1.daumcdn.net/cfile/tistory/2725EE4E5614C11009)
●레지스터 값들 출력하기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
|
![](https://t1.daumcdn.net/cfile/tistory/227339395614CD7732)
●레지스터 값들 출력하기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; } |
.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
|
![](https://t1.daumcdn.net/cfile/tistory/235DD7405614DB7805)
![](https://t1.daumcdn.net/cfile/tistory/2469A33F5614DB8B0C)