C언어(2020년)

16. RAM 에 대한 고찰

리더2333 2020. 11. 3. 12:46
반응형

메모리 카드를 RAM 이라고 하는데, RAM 은

Random Access Memory 의 약자이다.

임의 접근 기억 장치 라는 뜻인데,

 

만약 내 컴퓨터에 RAM 용량이 8Gbyte 라고 해보자.

 

char 는 1byte, int 는 4byte 라고 알고 있는데, 과연 8GByte 는 어느정도일까?

 

1 bit (1비트) : 1개의 진공관 또는 트렌지스터를 의미함 1개의 전구라고 생각하면 됨.

1 Byte (1바이트) : 8 bit 를 의미함

1 KByte (1킬로바이트) :  1024 Byte를 의미함

1 MByte (1메가바이트) : 1024 KByte를 의미함

1 GByte (1기가바이트) : 1024 MByte를 의미함

1 TByte (1테라바이트) : 1024 GByte를 의미함

 

우리는 1000 미터를 1 km (1킬로미터) 라고 하는데,

컴퓨터에서는 1024 byte 를 1 kbyte (1킬로바이트) 라고 한다.

왜 그럴까?

더보기

2진수 이기 때문이다.

10진수는 10, 100, 1000, 이런식으로 자리수 1개가 늘어날 때 10을 곱하는 것과 같고, 10의 3제곱이 될때 K 로 바꿔주는 것이다.

2진수는 1, 10, 100, 1000 이렇게 한자리 씩 늘어날때마다, 2, 4, 8, 16, 32 ... 2의 제곱으로 늘어나게 된다.

즉,

2

4

8

16

32

64

128

256

512

1024

2048

4096

...

이런식으로 되는데 2의 10제곱일때 1000과 가장 가깝다.

2의 10제곱이 1024 인 것이다.

 

 

십진수 1000 을 이진수로 표현하면 1111101000 이고,

십진수 1024 을 이진수로 표현하면 10000000000 이다.

 

즉, 이진수의 입장에서는 10000000000 이런 수를 K 로 대신해서 쓰자라는 말이 옳은 것이지

1111101000 이런 수 대신해서 K 로 쓰자라는 말은 옳치 못하다.

무언가 끝나지 않은 수를 대신해서 K 를 붙인다는건

십진수로 얘기하면 마치 1000 을 K 로 하자는게 아니라,

977 을 K 로 하자고 하면 무언가 이상하다.

 

 

 

 

그럼 8 bit 를 1 byte 라고 하는데, 그건 왜 그럴까?

더보기

옛날에는 4비트 6비트를 1바이트로 삼는 컴퓨터도 있었다고 한다.

하지만, 지금은 대개의 컴퓨터에서 8비트를 1바이트로 삼는다.

표준 C 언어에서도 8비트를 1바이트로 규정하고 있다.

 

예를 들어서 CDC 6000 계열의 메인 프레임은 60비트 부동 소수점 실수를

6비트짜리 바이트 10개로 나눴으며, 이 컴퓨터는 6비트를 1바이트로 삼았고, 따라서 로마자와 숫자만을 표현할 수 있는 천공 카드에 결과를 출력하기가 용이 했다고 한다.

 

또한, CDC 의 경우 12비트를 I/O를 사용했기 때문에 12비트를 1바이트라 부르기도 했다.

 

"byte" 는 1956년에 Dr. Werner Buchholz에 의해서 사용되었고, 이는 IBM의 IBM scratch computer를 디자인 하는 동안에 사용되었다. 이때는 4bit를 1byte로 설계되었다고 한다.

전형적인 I/O장비는 6bit를 1byte로 사용하다가, 나중에 System/360에 8bit를 1byte를 사용하기 시작하면서 규격이 정해지고 표준화 되었다.

 

ASCII 코드가 128개 이므로 7bit 면 충분했지만, 8비트를 사용하는 이유는

1비트는 통신에러를 확인하기 위함이라고 한다.

 

1 byte 를 1 character 라고 표현하는 이유 역시 1 byte 면 하나의 뜻을 전달 할 수 있기 때문이다.

 

 

어찌 되었던 우리가 프로그래밍을 할 때

char number = 0;

int number2 = 0;

이런 코드를 하면 무슨일이 일어날까?

 

바로 Random Access Memory 에 1 byte 가 할당되고 4 byte 가 할당된다는 것이다.

1 byte 가 할당된 곳의 별명은 number 이고

4 byte 가 할당된 곳의 별명은 number2 인 것이다.

물론 그 할당된 곳의 값은 0 으로 채워진다.

(2진수로 0은 1byte 의 경우 00000000 이고 4byte의 경우 00000000000000000000000000000000 이기 때문에 그에 해당하는 트랜지스터나 직접회로나 초고밀도 직접회로의 상태가 저런 상태가 된다는 뜻)

 

그럼 어디에 할당 되느냐~~~

Random 의 위치에 할당된다.

 

그래서 Random Access Memory 인 것이다.

 

그래도 어디에 할당되었는지 알고 싶다.

다음의 코드를 보자

#include <stdio.h>

int main()
{
	char number = 0;
	int number2 = 0;
	
	printf("%x\n", &number);
	printf("%x\n", &number2);

	return 0;
}

printf 문에 %x 를 사용했는데, 이것은 16진수의 값으로 표시 하라는 의미이다.

또한 printf 문에 numer 라고 사용한 대신에 &number 라고 사용했는데

이것은 number 라는 별명에 해당하는 곳의 주소(위치)를 의미한다.

 

 

실행결과 char 형인 number 는 fdf8d3 이라는 곳에 할당되었고,

int 형인 number2 는 fdf8c4 라는 곳에 할당되었다.

 

이것은 내 컴퓨터에서 현재 그런것이지, 다른사람 컴퓨터에서, 또는 다른 시간대에는

또 바뀔 것이다.

그때 그때마다 Random 이기 때문이다.

 

 

 

만약 메모리의 0x00000000 (맨처음) 주소에는 무슨 값이 들어있을까? 그 주소의 값을 바꾸면 무슨일이 일어날까?

더보기

이미 컴퓨터가 켜져 있으므로, 운영체제 및 기타프로그램이 실행되어져 있고,

이미 RAM 메모리는 사용되어지고 있다.

윈도우즈 운영체제에서 메모리를 관리 하고 있을 것이다.

사용자가 원하면(메모리 요청) ex) char number = 0; 에 의해서 요청됨

윈도우즈 시스템운영체제의 메모리 관리자가 놀고있는 메모리를 할당해서 허용해 줄 것이다.

별명 number 에 의해서 허용되어질 것이다.

 

하지만, 윈도우즈 시스템 운영체제의 메모리 관리자가 허용해준 메모리를 사용하지 않고,

유저가 임의의 메모리 예를들어 0x00000000 의 메모리에 대해 접근하여 값을 읽어 들이거나,

값을 변경하려고 시도하면, 윈도우즈 운영체제는 가만히 있지 않을 것이다.

윈도우즈 운영체제는 즉각 허용되지 않은 메모리를 참조하려하는 프로그램을 강제 종료 시킬 수도 있다.

 

만약 유저에게 모든 메모리 접근을 허용한다면 어떤일이 일어날까?

사용자는 특정 프로그램을 실행 시키고, 메모리 전체의 값을 조사하여,

특정 프로그램에서 특정 행위를 했을 때, 메모리의 값이 변하는 정도를 조사하여

데이터를 수집하고 연구하면, 특정 프로그램에 대해 해킹이 가능할 것이다.

여기에서 해킹 대상이 되는 특정 프로그램은 윈도우즈 운영체제가 될 수도 있다.

 

메모리는 운영체제에 의해서 관리되어지고, 할당되어지는데,

그래서 유저입장에서는 Random 으로 할당되어질 것이다.

만약에 유저가 원하는 곳의 메모리를 할당하게 해 준다 해도 결과는 마찬가지이다.

 

여러가지 보안상의 문제로 인하여, 메모리는 운영체제의 메모리 관리자에 의해 랜덤으로 할당되어지는게 맞다.

 

앞으로 C언어의 포인터를 배우게 될 것인데, 메모리 영역에 직접 접근하여, 값을 읽어들이던지 변경하게 된다.

위의 예제에 의하면 char 형인 number 는 fdf8d3 주소에 할당되었느데, 이 fdf8d3 이라는값을 포인트 변수에 저장하여 (number 라는 별명을 사용하지 않고) 주소에 접근하여 값을 변경한다는 의미인다.

 

#include <stdio.h>

int main()
{
	char number = 0;
	int number2 = 0;
	
	printf("%x\n", &number);
	printf("%x\n", &number2);

	char* pointer = 0;
	int* pointer2 = 0;
	
	pointer = &number;
	pointer2 = &number2;

	*pointer = 10;
	*pointer2 = 20;

	printf("%d\n", number);
	printf("%d\n", number2);

	return 0;
}

char* pointer = 0;

                          //char 형 주소를 받을 수 있는 포인터 변수 선언하고 현재 주소는 0x00000000 으로 초기화

int* pointer2 = 0;

                          //int 형 주소를 받을 수 있는 포인터 변수를 선언하고, 현재 주소는 0x00000000 으로 초기화

pointer = &number;     //number 의 주소를 받음

pointer2 = &number2;  //number2 의 주소를 받음

*pointer = 10;             //주소가 가르키는 곳의 값을 10으로 변경

*pointer2 = 20;            //주소가 가르키는 곳의 값을 20으로 변경

 

실행 결과

숙제) char* pointer = 0; 이후

pointer = &number; 를 하지 않고

*pointer = 10; 이렇게 하면 무슨일이 일어나는지 확인하기.

 

반응형

'C언어(2020년)' 카테고리의 다른 글

18. 연산자 우선순위  (0) 2020.11.03
17. 포인터  (1) 2020.11.03
15. 주석  (0) 2020.11.03
14. 배열  (0) 2020.11.02
13. for 문  (0) 2020.11.02