20140409 (CPU, Microcontroller, RAM, ROM, RISC, CISC, 구조체, #pragma pack)

38일차

 

 

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

상     식

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

 

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

--- CPU, Microcontroller

 

- CPU는 위의 그림과 같이 core만 있고

RAM, ROM, I/O... 다른 것들은 외부에 있는 개인컴퓨터의 것과 같은 것.

 

- Microcontroller는 칩에 core, SDRAM, EEPRAM,... 등등 다른 것들이 함께 들어 있는 것.

 

 

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

- RAM, ROM 등등 메모리

 

- RAM (Ramdom Access Memory)

읽기 쓰기가 언제나 가능하다.

휘발성 ( 전기가 끊기면 내용이 다 날아감 )

 

- ROM (Read Only Memory)

읽기만 가능

비휘발성 ( 전기가 끊겨도 내용이 저장되어 있다 )

 

- EEPROM (Electrically Erasable Programmable ROM)

읽기 쓰기 가능

비휘발성

RAM보다 비싸다

 

- Flash Memory

읽기 쓰기 가능

비휘발성

RAM, ROM보다 느리다

RAM보다 가격이 비싸, EEPROM보다 싸다

 

- SRAM (Static RAM)

전기가 가해지면 안에 내용을 유지해서 정적이라고 함.

주로 캐시메모리

DRAM에 비해 비싸다

 

- DRAM (Dynamic RAM)

전기가 가해져도 일정시간이 지나면 내용이 바뀌므로

주기적으로 전기를 다시 공급해 줘야한다. Reflesh 그래서 동적이라고 함.

주로 주기억장치

SRAM에 비해 싸다

 

- SDRAM

DRAM 업그레이드 판.

 

 

 

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

--- RISC, CISC

            구조, 명령어          주 사용                      비유?

RISC         단순           서버, 슈퍼컴퓨터             물 끓이고, 스프넣고, 라면 넣고...

CISC         복잡                   PC                       라면 끓여 끝.

명령세트의 종류로 CPU에 기계어 코드이다

CISC 가 먼저 세상에 나왔는데 명령어가 엄청나게 많았다.

하지만 그 중에 실제로 자주 쓰이는 것은 10%미만에 불과하다는 것을 알아내고

자주 쓰는 것을 모아서 만든 것이 RISC 방식이라고 한다

현재에는 둘 다 서로의 장점을 수용하게 되서 경계가 무너지고 있다고들 한다...

 

 

 

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

--- WinAVR

AVR에 넣는 프로그램짜는 컴파일러

폴더 내에 main.c와 makefile이 함께 있어야 한다.

 

- make

컴파일 명령어

- make clean

컴파일한 파일 다 지우기

- main.hex

실행 파일

 

 

 

 

C 언어

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

구    조    체

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

- 구조체 사이즈 출력

ex)

#include <stdio.h>

struct smart
{
  int a;
};

int main()
{
  printf("%d \n"sizeof(struct smart));

  return 0;
}

- struct smart  이것 자체가 자료형이다.

 

 

여기서 알 수 없는 것이 있었다....

ex)

#include <stdio.h>

struct smart
{
  int a;  //  4  4
  int b;  //  8  8
};

int main()
{
  printf("%d \n"sizeof(struct smart) );

  return 0;
}

출력 화면 

문제가 없다.

아래를 더 보자

#include <stdio.h>

struct smart
{
  int a;  //  4  4
  int b;  //  8  8
  char c;  //  9  12
};

int main()
{
  printf("%d \n"sizeof(struct smart) );

  return 0;

}

출력 화면

??? 9가 나와야 하는데 12가 나왔다.

변수 // 예상크기  결과크기

#include <stdio.h>

struct smart
{
  int a;  //  4  4
  int b;  //  8  8
  char c;  //  9  12
  char d;  //  10  12
  char e;  //  11  12
  short f;  //  13  16
  char g;  //  14  16
  int h;  //  18  20
  char i;  //  19  24
  short j;  //  21  24
  char k;  //  22  28
};

int main()
{
  printf("%d \n"sizeof(struct smart) );

  return 0;
}

왜 그러냐면 컴파일러는 4byte or 2byte로 잡는게 편하기 때문에? 컴파일 편한대로? 메모리를 잡기 때문에 저런 현상이 나타난다고 한다.

 

아래 그림을 통해 메모리 구조를 보자. 

①번은 위에서 선언한 변수 순서 그대로 했을 경우 메모리가 잡히고 빈칸은 버리는 공간이 되어버렸다. 그래서 6byte 낭비.

②번은 변수 선언을 메모리가 잡히는 구조를 생각해서 A, B, F, J, C, D, E, G, H, I, K 순으로 선언 했을 경우 2번과 같이 메모리가 잡힌다. 2byte낭비.

③번은 메모리 위에 #pragma pack(1) 이라는 것이 있는데, 구조체 선언 위에 선언할 경우 컴파일러가 메모리를 잡을 때 1byte단위씩 잡게된다. 딱 맞다.

④번은 구조체 선언 위에 #pragma pack(1), 구조체 선언 밑에 #pragma pack(4) 를 선언한 경우이다. 딱 맞다.

 

장단점 비교

①번이 제일 쓰레기 코드다. 대신 프로그래머가 편하다.

②번은 ①번에 비해 메모리를 4byte를 확보. 프로그래머가 신경을 좀 써야된다.

③번은 ①번에 비해 메모리를 6byte나 확보했지만, 속도가 느리다. 편하다.

④번은 ①번에 비해 메모리 6byte 확보, 속도도 확보 가장 좋은 코드. 프로그래머가 신경 좀 써야된다.

 

 

- #pragma pack( )

위에서 한 번 언급 했듯이 컴파일시 메모리 단위를 바꾼다.

ex)

#include <stdio.h>
#pragma pack(1)

struct smart
{
 int a;  //  4  4
 int b;  //  8  8
 char c;  //  9  12
 char d;  //  10  12
 char e;  //  11  12
 short f;  //  13  16
 char g;  //  14  16
 int h;  //  18  20
 char i;  //  19  24
 short j;  //  21  24
 char k;  //  22  28
};

#pragma pack(4)

struct smart1
{
 int a; 
 int b; 
 char c;  
 char d; 
 char e; 
 short f; 
 char g; 
 int h;
 char i; 
 short j; 
 char k;  //  28
};

int main()
{
 printf("smart : %d \n", sizeof(struct smart) );
 printf("smart1: %d \n", sizeof(struct smart1) );

 return 0;
}

출력 화면 

 

 

 

- 메모리에 진짜로 위와 같이 저장되는지 변수들의 주소값 확인

1번의 경우로 확인.

ex)

#include <stdio.h>

struct smart
{
int a; // 4 4
int b; // 8 8
char c; // 9 12
char d; // 10 12
char e; // 11 12
short f; // 13 16
char g; // 14 16
int h; // 18 20
char i; // 19 24
short j; // 21 24
char k; // 22 28
};

int main()
{
 struct smart ass;

 printf("int a\t: 0x%08X \n", &ass.a);
 printf("int b\t: 0x%08X \n", &ass.b);
 printf("char c\t: 0x%08X \n", &ass.c);
 printf("char d\t: 0x%08X \n", &ass.d);
 printf("char e\t: 0x%08X \n", &ass.e);
 printf("short f\t: 0x%08X \n", &ass.f);
 printf("char g\t: 0x%08X \n", &ass.g);
 printf("int h\t: 0x%08X \n", &ass.h);
 printf("char i\t: 0x%08X \n", &ass.i);
 printf("short j\t: 0x%08X \n", &ass.j);
 printf("char k\t: 0x%08X \n", &ass.k);

 return 0;
}

출력 화면

 

 

메모리 구조와 비교 

 

- e 다음에 f 가 한칸 37비우고 38부터 시작하는 것을 볼 수 있다.

j 도 i 다음에 41부터 시작이 아니라 42부터 시작하는 것을 볼 수 있다.

 

 

 

 

 

 

 

 

 

 

설정

트랙백

댓글

20140408 (회로도 최적화, 4bit 덧셈, 구조체)

37일차

 

 

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

회로도 최적화

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

- 어제 했던 내용을 이어서

어제는 sum을 계산했고 오늘은 carry를 계산한다.

방식은 같다. 

 

실습

 

A     1

B     1

Ci    1 

인 경우

 

 

A     1

B     1

Ci    0 

인 경우

 

 

A     0

B     1

Ci    0

인 경우

 

 

A     0

B     0

Ci    0 

인 경우

 

 

--- 4bit 덧셈

4bit 덧셈을 하려면 전가산기 3개와 반가산기 1개가 필요하다

 

 

 

 

--- ATMEL

- 메모리 회사

- cpu사업도 시작했음.

- cpu 시리즈 중에 AVR, AT91.. 등등 있음

- AVR 시리즈 중에 Mega 모델 중 ATMega128을 공부할 예정.

 

--- ATMega128

- Microcontroller

- 8bit

- 128 Flash Memory

 

 

 

 

 

 

 

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

구  조  체

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

- 새로운 타입을 정의.

typedef와 다른점은 아래를 참고하자.

 

struct (타입이름)

{ (내용) };

 

- 전역에서 사용해야 하니 전역에 정의.

 

ex)

#include <stdio.h>

struct smart
{
  char  Name[7];
  char  Phone[14];
  int  Age;
};

int main()
{
  struct smart  people[3];
  int    iCnt;

  for(iCnt = 03 > iCnt; ++iCnt)
  {
    printf("이름 : ");
    scanf("%s", people[iCnt].Name);
    fflush(stdin);

    printf("전화번호 : ");
    scanf("%s", people[iCnt].Phone);
    fflush(stdin);

    printf("나이 : ");
    scanf("%d"&people[iCnt].Age);
  }

  for(iCnt = 03 > iCnt; ++iCnt)
  {
    printf("이름 : [%s], 전화번호 : [%s], 나이 : [%d] \n", people[iCnt].Name, people[iCnt].Phone, people[iCnt].Age);
  }

  return 0;
}

이런식으로 사용.

 

- 초기화

#include <stdio.h>

struct employee
{
  char  Name[7];
  char  Phone[14];
  int  Age;
};

struct employer
{
  char  Name[7];
  char  Phone[14];
  int  Age;
};

int main()
{
  struct employee  people[3= {
      {"James""010-0100-0101"10000},
      {"Ayin""010-1111-2220"9999},
      {"Watson""010-1234-5678"8000}
      };
  struct employer  CEO = {"IamCEO""000-0000-0000"40000};
  int    iCnt;

  printf("이름 : [%s], 전화번호 : [%s], 나이 : [%d] \n", CEO.Name, CEO.Phone, CEO.Age);
  
  for(iCnt = 03 > iCnt; ++iCnt)
  {
    printf("이름 : [%s], 전화번호 : [%s], 나이 : [%d] \n", people[iCnt].Name, people[iCnt].Phone, people[iCnt].Age);
  }

  return 0;
}

출력 화면

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

설정

트랙백

댓글

과제 : 문자열치환

잡다 2014. 4. 8. 14:09

 

 

처음 한 소스

#include <stdio.h>
#include <string.h>

char * Change_word(char * string, char * old_word, char *new_word);

int main()
{
  char  caOld_word[32];
  char  caNew_word[32];
  char  caString_word[50];

  fputs("Input String : ", stdout);
  fgets(caString_word, 31, stdin);
  fflush(stdin);

  fputs("Choose String to modify : ", stdout);
  fgets(caOld_word, 11, stdin);
  fflush(stdin);

  fputs("Input String to modify : ", stdout);
  fgets(caNew_word, 11, stdin);
  fflush(stdin);

  Change_word(caString_word, caOld_word, caNew_word);

  printf("Output String : %s \n", caString_word);

  getchar();

  return 0;
}

char * Change_word(char * string, char * old_word, char *new_word)
{
  int  iLength_old = 0;
  int  iLength_new = 0;
  int  iCnt_old = 0;
  int  iCnt_new = 0;
  int  iCnt1 = 0;
  int  iCnt2;
  int  iCnt_temp;
  char  caTemp[50= "";

  // ----------------------------- // 수정 문자 길이 시작
  while('\n' != old_word[iLength_old] && 0 != old_word[iLength_old] )
  {
    ++iLength_old;
  }

  while('\n' != new_word[iLength_new] && 0 != new_word[iLength_new] )
  {
    ++iLength_new;
  }

  // ---------------------------- // 수정 문자 길이 종료

  // ---------------------------- // 문자열 찾아 바꾸기 시작
  while(0 != string[iCnt1])
  {
    if(string[iCnt1] == old_word[iCnt_old]) //--- 첫 문자가 맞으면 뒷문자 확인
    {
      ++iCnt_old;
      for(iCnt2 = 1; iLength_old > iCnt2; ++iCnt2)
      {
        
        if(string[iCnt2+iCnt1] == old_word[iCnt_old])
        {
          if(iCnt_old == iLength_old-1)  //--- 끝까지 다 일치하면 치환
          {
            strcpy(caTemp, string);

            for(iCnt2 = 0; iLength_new > iCnt2; ++iCnt2)  //--- new로 바꾸기
            {
              string[iCnt2+iCnt1] = new_word[iCnt_new];
              ++iCnt_new;
            }

            iCnt_temp = iCnt1 + iLength_old;
            iCnt2 = iCnt2 + iCnt1;

            while(0 != caTemp[iCnt_temp])   //--- 나머지 문자열 넣기
            {
              string[iCnt2] = caTemp[iCnt_temp];
              ++iCnt2;
              ++iCnt_temp;
            }
            string[iCnt2] = 0;

            return string;  //--- 함수 끝
          }
          else
          {
            ++iCnt_old;
          }
        }
        else
        {
          break;
        }
      }
      iCnt_old = 0;
    }
    ++iCnt1;
  }
  // ---------------------------- // 문자열 찾아 바꾸기 종료

  return string;
}

main_before.exe

 

 

문자열 함수를 사용한 코드

#include <stdio.h>
#include <string.h>

char * Change_word(char * string, char * old_word, char *new_word);

int main()
{
  char  caOld_word[32];
  char  caNew_word[32];
  char  caString_word[50];

  fputs("Input String : ", stdout);
  fgets(caString_word, 31, stdin);
  fflush(stdin);

  fputs("Choose String to modify : ", stdout);
  fgets(caOld_word, 11, stdin);
  fflush(stdin);

  fputs("Input String to modify : ", stdout);
  fgets(caNew_word, 11, stdin);
  fflush(stdin);

  Change_word(caString_word, caOld_word, caNew_word);

  printf("Output String : %s \n", caString_word);

  getchar();

  return 0;
}

char * Change_word(char * string, char * old_word, char *new_word)
{
  int  iCnt;
  int  iCnt2;
  int  iCntOld = 0;
  int  iLengthNew = strlen(new_word);
  int  iLengthOld = strlen(old_word);
  char  temp[50];

  if('\n' == new_word[iLengthNew-1])
  {
    --iLengthNew;
  }

  if('\n' == old_word[iLengthOld-1])
  {
    --iLengthOld;
  }

  for(iCnt = 00 != string[iCnt]; ++iCnt)
  {
    if(string[iCnt] == old_word[iCntOld])  // 첫번째 문자 일치?
    {
      iCnt2 = 1;  // 두번째 부터 시작
      iCntOld = 1;  //       ``

      while(iCnt2 < iLengthOld)  // 나머지 문자 일치
      {
        if(string[iCnt2+iCnt] == old_word[iCntOld])
        {
          if(iCnt2 == iLengthOld-1)  // 마지막 문자인가?
          {
            strcpy(temp, &string[iCnt+iCnt2+1]);
            strcpy(&string[iCnt], new_word);
            strcpy(&string[iCnt+iLengthNew], temp);

            return string;
          }
          ++iCnt2;
          ++iCntOld;
        }
        else
        {
          iCntOld = 0;
          break;
        }
      }
    }
  }

  return string;
}

main.exe

 

'잡다' 카테고리의 다른 글

간단한 포토샵  (0) 2014.07.21
Raw socket  (0) 2014.06.28
Mac Address, 제조회사  (0) 2014.06.27
[vi명령어] 자동정렬 / 단어찾기 / 도스저장  (0) 2014.06.25
GNU Compiler __attribute__  (0) 2014.06.19

설정

트랙백

댓글