728x90

windows는 MBCS와 WBCS를 모두 사용가능한 프로그램 구현을 위해 매크로를 정의하고 있다.

#ifdef UNICODE

           typedef  WCHAR TCHAR;

           typedef  LPWSTR LPTSTR;

           typedef  LPCWSTR LPCTSTR;

#else

           typedef  CHAR TCHAR;

           typedef  LPSTR LPTSTR;

           typedef  LPCSTR LPCTSTR;

#endif

 

아래는 windows.h에 포함되지 않는 tchar.h 에 선언된 일부이다.

#ifdef _UNICODE

        #define  __T(x)   L##x

#else

        #define  __T(x)    x

 

#define     _T(x)      __T(x)

#define     _TEXT(x)   __T(x)

 

 

ex)

TCHAR arr[10];

위 선언이 되어 있고 UNICODE 매크로가 정의되어 있지 않다면 CHAR arr[10];이다.

UNICODE 매크로가 정의되어 있다면  WCHAR arr[10];이다.

 

매크로 UNICODE가 정의되어있다면

TCHAR arr[10];   ->   WCHAR arr[10];     ->     wchar_t arr[10];

매크로 UNICODE가 정의되어 있지 않다면

TCHAR arr[10];   ->    WCHAR arr[10];   ->     char arr[10];

 

ex)

__T("ABCDE");

위. 선언이 있고 _UNICODE 매크로가 정의되어 있지 않다면, MBCS타입 문자열로 변경된다.

"ABCDE"

 

_UNICODE 매크로가 정의되어 있다면 WBCS기반의 문자열이 된다.

L"ABCDE"

 

매크로 _UNICODE가 정의되면

_T("ABCDE")   ->     __T("ABCDE")    -> L"ABCDE"

매크로 _UNICODE가 정의되어 있지 않다면

_T("ABCDE")   ->     __T("ABCDE")     -> "ABCDE"

 

MBCS와 WBCS(유니코드)를 동시에 지원하기 위한 함수들

tchar.h에 있는 MBCS, WBCS매크로

#ifdef _UNICODE

                #define              _tmain                     wmain

                #define              _tcslen                     wcslen

                #define              _tcscat                     wcscat

                #define              _tcscpy                    wcscpy

                #define              _tcscmp                   wcscmp

                #define              _tprintf                    wprintf

                #define              _tscanf                    wscanf

                #define              _fgetts                    fgetws

                #define              _fputts                    fputws

#else

                #define              _tmain                     main

                #define              _tcslen                     strlen

                #define              _tcscat                     strcat

                #define              _tcscpy                    strcpy

                #define              _tcscmp                   strcmp

                #define              _tprintf                    printf

                #define              _tscanf                    scanf

                #define              _fgetts                    fgets

                #define              _fputts                    fputs

#endif

 

printf("string length : %d \n", size);

위 문장은 MBCS기반으로 컴파일된다. 유니코드기반으로 컴파일하기 위해선 아래처럼 바꿔야 한다.

wprintf(L"string length : %d \n",size);

MBCS, WBCS기반으로 _UNICODE 정의에 따라 달라지는 함수들의 선언이 tchar.h에 선언되어 있다.  

728x90
728x90

window에서의 유니코드(UNICODE)

 

아스키코드 : 미국에서 정의하고 있는 표준 알파벳 26개와 몇몇 확장문자(수학기호, 악센트 기호)등을 합쳐 256개 즉 1바이트로 표현이되는 문자들이다.

 

유니코드 : 영어가 아닌 다른 국가에서 사용하는 문자들을 표현하기 위해 등장했다. 유니코드는 문자를 표현하는데 균일하게 2바이트를 사용한다. 2바이트 크기인 65536개의 문자를 표현할 수 있다. 한글, 영어를 포함한 전세계의 다양한 문자, 다양한 기호를 표현가능하다.

 

문자셋의 종류

1.SBCS(Single Byte Character Set)

문자를 표현하는데 있어서 1바이트만 사양하는 방식. 아스키 코드가 대표적인 SBCS이다.

 

2.MBCS(Multi Byte Character Set)

어떤문자는 1바이트, 어떤문자는 2바이트로 표현한다. 유니코드는 MBCS에 속하지 않는다. MBCS는 SBCS를 포함하고 있다. 아스키 코드에서 정의한 문자들은 1바이트로 처리하고, 아스키코드에서 정의하지 않은 다른문자를 표현할 때는 2바이트로 처리한다. MBCS에서 영어는 1바이트로, 한글은 2바이트로 처리된다.

 

3.WBCS(Wide Byte Charactor Set)

유니코드가 WBCS방식에 해당한다. WBCS는 모든 문자를 2바이트로 처리하는 문자셋이다.

 

ex)

str = "ABC한글"

sizeof(str)은 8이다.

strlen(str)은 7이다.

 

8바이트가 나온것은 ABC(3바이트) + 한글(4바이트) + NULL(1바이트)해서 총 8바이트이다. 이것은 현재 MBCS 기반으로 실행되고 있는 것이다.

 

문자열길이는 7이라고 출력되었다. 문자열 길이에서 NULL은 제외된다. "ABC한글"은 실제로 문자열길이는 5지만 "한글"이라는 단어가 4로 인식되고 있다. 이와 같은 문제점이 MBCS의 문제점이다.

 

MBCS 방식의 문제점을 해결하는 것이 WBCS방식이다. WBCS방식은 모든 문자들을 2바이트로 처리한다.

 

 

WBCS 기반의 프로그래밍

 

WBCS 프로그래밍에서는 char 대신 wchar_t를 사용해야 한다. char형은 1바이트만 할당되지만 wchar_t형 변수는 2바이트 메모리 공간이 할당된다. wchar_t를 통해 유니코드를 기반으로 문자를 표현하는 것이 가능하다.

 

wchar_t의 자료형

typedef unsigned short wchar_t;

 

"ABC"대신 L"ABC"를 사용해야한다.

ex) wchar_t str[] = L"ABC"

문자열앞의 L은 유니코드 기반(WBCS 기반)으로 표현하라는 의미를 가지고 있다. 위 경우에는 "ABC"는 NULL을 포함해 총 8바이트로 표현된다. 유니코드에서는 NULL문자 까지도 2바이트로 처리된다.

 

문자열 조작 함수

      SBCS                                                      WBCS

     strlen                                      size_t wcslen(const wchar_t * string);

     strcpy                                     wchar_t * wcscpy(wchar_t * dest, const whcar_t * src);

     strncpy                                   wchar_t * wcsncpy(wchar_t * dest, const wchar_t * src, size_t cnt);

     strcat                                     wchar_t * wcscat(wchar_t * dest, const wchar_t * src);

     strncat                                    wchar_t * wcsncat(wchar_t * dest, const wchar_t * src, size_t cnt);

     strcmp                                   int wcscmp(const wchar_t * s1, const wchar_t * s2);

     strncmp                                 int wcsncmp(const wchar_t * s1, const wchar_t *s2, size_t cnt);

 

WBCS기반 함수의 전달인자는 모두 유니코드 기반 문자열이다.

 

입출력 함수

printf("Hello World!");

"Hello World!"는 아스키코드에 존재하는 문자들로만 구성되어 있으므로 문자당 1바이트로 표현된다. printf함수는 SBCS기반 문자열을 처리하는 함수다. 유니코드 기반으로 작성할려면 아래와 같이 작성해야 한다.

wprintf(L"Hello World!");

printf함수의 유니코드 버전이 wprintf 함수이다.

 

     SBCS                                                         WBCS

   printf                                                      int wprintf(const wchar_t * format [ ,argument] ....);

   scanf                                                      int wscanf(const wchar_t * format [ ,argument]......);

   fgets                                                        wchar_t * fgetws(wchar_t * string, int n, FILE * stream);

   fputs                                                       int fputws(const wchar_t * string, FILE * stream);

 

 

wmain은 프로그램 실행시 전달되는 문자열을 유니코드 기반으로 구성한다는 의미이다.

 

 

 

 

728x90
728x90

데이터를 이동하는데 사용되는 전송경로를 버스 시스템(Bus System)이라고 한다. 버스 시스템은 주고 받는 데이터의 종류에 따라서 어드레스 버스(Address Bus), 데이터 버스(Data Bus), 컨트롤 버스(Control Bus) 이렇게 3가지 요소로 구성된다.

 

I/O 버스는 CPU, 키보드, 하드디스크 등등 컴퓨터 내외부의 주변장치들과 연결되어 있다. 이렇듯 I/O 버스는 여러 장치들이 데이터를 주고받기 위한 통로 역할을 한다.

 

CPU와 메인 메모리도 데이터를 주고받기 위해서 버스로 연결되어 있다. 메인메모리에서 CPU로 명령어들을 가져오는 연산(Fetch)와 CPU에서 계산된 덧셈결과를 메인 메모리에 저장하는 작업등을 위해 버스로 연결되어 있다.

각각의 버스 용도

 

데이터 버스(Data Bus) : 데이터를 이동시키기 위해 필요한 버스이다. 데이터란 명령어, 연산에 필요한 피연산자(Operand) 등등 이다.

 

어드레스 버스(address Bus) : 주소값을 이동하기 위해 필요한 버스이다. 왜 주소값을 이동해야 하는가? 예를 들어 CPU가 0x512번지에 저장되어 있는 데이터 4바이트를 읽을려고 가정할 때 메모리 영역에 주소값 0x512를 먼저 전달해야 한다. 이때 사용되는 것이 어드레스 버스이다. 메모리는 0x512 번지에 존재하는 4바이트 데이터를 데이터 버스를 통해서 전달받게 된다.

 

컨트롤 버스(Control Bus) : CPU가 원하는 바를 메모리에 전달할 때 사용된다. 쉽게 말해서 CPU와 메모리가 특별한 사인(sign)을 주고 받는 용도로 사용되는 버스이다.

 

728x90
728x90

프로그램의 실행과정

 

실행파일의 생성과정

전처리기 -> 컴파일러 -> 어셈블러 -> 링커

 

1.전처리기의 치환 작업

전처리기는 '#include', '#define'과 같이 '#'으로 시작하는 지시자의 지시에 따라서 소스코드를 적절히 변경하는 작업을 한다.

 

2.컴파일러에 의한 번역

전처리기에 의해 변경된 소스코드는 여전히 C언어로 구성되어 있다. 이 소스코드는 컴파일러에 의해서 어셈블리 코드로 번역된다.

 

3.어셈블러에 의한 바이너리 코드생성

바이너리코드는 1과 0으로만 구성되는 코드이다. 컴파일러에 의해 번역된 어셈블리 코드는 컴퓨터에 의해 실행되기 앞서서 바이너리 코드로 번역 되어야 한다. 컴퓨터는 1과 0만 이해하기 때문이다. 이처럼 CPU가 이해할 수 있는 바이너리 코드로 바꾸어 주는 프로그램이 어셈블러이다.

 

4.링커에 의한 연결과 결합

링커는 프로그램 내에서 참조하는 함수나 라이브러리들을 하나로 묶는(혹은 연결시켜 주는)작업을 한다고 설명할 수 있다. 이 과정이 끝나면 실행파일이 생성된다. 실행파일은 바이너리 코드로 구성된다.

 

 

위 과정을 통한 프로그램 실행 과정

위 실행파일은 링커에 의해서 최종적으로 만들어진 파일이다. 실행 파일 안에는 컴퓨터에게 일을 시키기위한 명령어(바이너리 코드)가 들어있다. 실행파일이 메모리에 올라가고 난 다음 CPU에 의해 실행되기 시작한다.

 

메모리에 올라간 명령어들은 CPU에 의해서 순차적으로 실행된다. 명령어 A, 명령어 B, 명령어 C 순서대로 이다. 이명령어 들은 메모리에서 실행되는 것이 아니라 CPU내부로 하나씩 이동한 다음 실행시킨다.

 

명령어 실행 과정

1.Fetch : 메모리상에 존재하는 명령어를 CPU로 가져오는 작업이다.

2.Decode : 가져온 명령어를 CPU가 해석하는 단계이다. 즉, 무슨일을 하라는 명령어인지 분석하는 단계이다.

3.Execution : 해석된 명령어의 명령대로 CPU가 실행하는 단계이다.

 

하드웨어 구성의 재접근

명령어의 내용이 산술 및 논리연산이라면 산술 및 논리 연산을 하는 Execution의 주체는 ALU(Arithmetic Logic Unit)이다.

 

Decode단계는 CPU안에 있는 컨트롤 유닛이 Decode 즉 명령어 해석을 진행한다.

 

메인메모리에서 CPU로 가져온 명령어는 레지스터에 저장된다. 레지스터 중에서도 IR(Instruction Register)이라 불리는 레지스터에 저장된다.

 

 

 

728x90
728x90

시스템 프로그램 : 컴퓨터 시스템을 동작시키는 프로그램 즉, 컴퓨터를 동작(파일복사, 파일 이동 등등)을 시키기 위해 필요한 프로그램. 

ex) window, linux와 같은 시스템 프로그램

-> 시스템 프로그램이란 하드웨어를 사용할 수 있도록 도와주는 프로그램

 

windows 시스템 프로그램이란 windows 운영체제 기반의 컴퓨터에게 일을 시키기 위한 프로그램

 

컴퓨터 시스템의 주요 구성요소

하드웨어의 구성

           

CPU(Central Processing Unit)

중앙 처리 장치가 CPU이다. CPU는 프로그램 실행에 있어서 핵심적인 역할을 담당한다. 컴퓨터의 '머리'부분이다.

 

메인 메모리(Main Memory)

램(RAM)으로 구성되는 메인 메모리는 컴파일이 완료된 프로그램 코드가 올라가서 실행되는 영역이다. 메인 메모리는 프로그램 실행을 위해 존재한다.

 

입출력 버스(Input/ Output Bus)

입출력 버스는 컴퓨터 구성요소 사이의 데이터 송수신을 위해 사용되는 경로이다. 주고받는 데이터의 종류와 역할에 따라 어드레스 버스(Address Bus), 데이터 버스(Data Bus), 컨트롤 버스(Control Bus) 이렇게 세가지로 구분된다.

하드디스크, 메인메모리, CPU 등등이 모두 버스에 연결되어 있다. 버스 시스템을 기반으로 하드디스크에 있는 데이터를 메인메모리로, 메인메모리에 있는 데이터를 하드디스크로 전송하는 것이 가능하고, 메인 메모리와 CPU 사이에서의 데이터 입출력도 가능하다.

 

CPU에 대한 이해

 

ALU(Arithmetic Logic Unit)

CPU 내부에서 실제 연산(덧셈 뺄셈 등등)을 담다한다. ALU가 처리하는 기본적인 연산은 크게 두가지이다. 하나는 덧셈이나 뺄셈과 같은 산술연산이고, 나머지 하나는 AND와 OR와 같은 논리연산이다. 아주 복잡한 프로그램도 CPU 입장에서는 대부분 이 두가지 형태의 연산으로 이루어 진다.

 

컨트롤 유닛(Control Unit)

소스코드를 컴파일 하면 실행파일이 생성된다. 이 실행 파일에는 CPU에게 일을 시키기위한 명령어들이 저장되어 있다.

어떤 경로를 거치던 간에 이 명령어가 CPU내부로 들어가야 CPU에게 일을 시킬 수 있다.

CPU내부로 들어간 명령어가 무엇을 하라는 것인지 ALU는 이해할 수 없다. (ALU는 산술연산과 논리연산만 가능하기 때문이다.) ALU를 대신해서 이러한 명령어를 해석해주는 구성요소가 컨트롤 유닛이다.

컨트롤 유닛은 CPU가 처리해야할 명령어들을 해석한다. CPU내부로 들어온 명령어를 해석하고 덧셈을 하라는 명령어가 나온다면 ALU에게 덧셈을 하도록 신호를 보낸다. 컨트롤 유닛은 명령어를 해석하고 해석된 결과에 따라 적절한 신호를 CPU의 다른 블록에 보내는 일을 한다.

 

CPU내부에 존재하는 레지스터들(Register Set)

컨트롤 유닛이나 ALU가 필요로 하는 명령어 및 데이터들을 저장하기 위한 메모리 공간이다. 임시 데이터 저장 장소에서 상황이 된다면 컨트롤 유닛과 ALU가 직접 데이터를 가져간다.

이러한 레지스터들은 CPU 내부에 여러개가 존재하는데 CPU의 종류에 따라 그 개수와 형태가 다양하다. 레지스터들은 각각의 용도가 정해져 있는것이 일반적이며 이들은 CPU가 연산을 하기위해 반드시 필요하다.

 

버스 인터페이스(Bus Interface)

명령어와 데이터들이 CPU안으로 잘 흘러들어가는것이 가능한 이유는 버스 인터페이스가 있기 때문이다.

 

CPU, 하드디스크, RAM, 사운드 카드, 그래픽 카드 등은 서로 데이터를 주고 받으면서 동작한다. 서로 데이터를 주고받기 위한 매개체가 I/O버스(BUS)이다.

CPU에서 버스에 접근이 가능한데 이것은 CPU내에 I/O버스의 통신 방식을 이해하고 있는 무엇인가가 있어야만 한다. 이러한 역할을 하는것이 '버스 인터페이스'이다.

버스 인터페이스는 버스가 어떻게 데이터를 전송하는지, 그에 대한 프로토콜 혹은 통신방식을 알고 있다. CPU는 버스 인터페이스를 통해 내부에 저장되어 있는 데이터(레지스터에 저장되어 있는 데이터)를 I/O버스에 내보내기도하고 I/O버스를 통해 들어오는 데이터들을 수신하기도 한다.

 

클럭 신호

클럭신호는 타이밍(Timing)을 제공하기 위해서 필요하다.

CPU클럭 속도가 16Mhz라면 컴퓨터에 있는 클럭발생기(오실레이터)는 1초당 1,600,000번의 클럭을 발생시키게 된다. 그리고 CPU는 매 클럭이 발생할 때마다 그 클럭에 맞춰서 일을한다. 즉 클럭 속도가 1.6Mhz인 CPU는 1초에 1백6십만번 연산을 하게 된다. 클럭 발생기에 의해 발생되는 클럭 신호(Clock Pulse)는 CPU를 구성하는 요소에 제공되며, 이 신호에 맞춰서 CPU가 일을 한다.

 

CPU가 클럭 신호에 맞춰 일하는 이유는  컴퓨터 시스템은 동기화를 필요로 하기 때문이다.

728x90

+ Recent posts