Post List

2018/03/13

System__32Bit_64Bit


이번에는 64비트 검퓨터와 32비트 컴퓨터의 구분방법 대해서 알아보겠습니다.

아래 그림을 보면 메모리에 올라온 명령어를 CPU 전송하여 CPU내부에서 연산을 처리하기 위한 과정을 간략하게 보여주고있습니다.





CPU I/O버스를 통해서 데이터를 외부로 전송하기도 하고, CPU내부로 수신하기도 합니다. 이때  번에 전송 수신할 있는 데이터의 크기에 따라서 32비트 시스템과 64비트 시스템이 나뉘게 됩니다.
CPU 버스를 통해서 번에 전송 수신할 있는 데이터의 크기가 32비트면 32비트 컴퓨터이고, 64비트면 64비트 컴퓨터가 됩니다.
하나의 기준은 데이터 처리능력입니다. CPU 외부로부터 들어오는 데이터를 처리해야 하는데, 32비트 컴퓨터는 번에 32비트 데이터를, 64비트 컴퓨터는 번에 64비트 데이터를 처리할 있습니다.

, 번에 송수신할 있는 데이터 크기 번에 처리할 있는 데이터 크기 기준으로 32비트 컴퓨터와 64비트 컴퓨터를 구분 짓는다 입니다.

프로그래머 입장에서 보면 표현할 있는 주소값의 범위가 넓으면 넓을수록 좋습니다. 메모리 공간만 충분하다면 주소값의 범위가 넓은 만큼 넓은 메모리 공간을 활용할 있기 때문이지요. 예를 들어서 메모리는 1G바이트 정도 되는데, 주소값을 표현하기 위해서 4비트가 사용된다면, 메모리에 할당할 있는 주소값의 개수는 2 4승에 해당하는 16바이트가 전부입니다. 따라서 사용할 있는 최대 메모리의 크기는 16바이트가 됩니다.

그렇다면 32비트 컴퓨터에서 주소값 표현을 위해 비트를 활용하는 것이 좋을까요?
표현할 있는 주소의 범위가 넓으면서 연산속도도 빠르게 구성해야 합니다. 두가지 측면을 고려한다면, 32비트 컴퓨터에서는 32비트가 최선의 선택입니다.

32비트가 최선의 선택일까요,
한번에 처리할 있는 데이터(주소값 포함) 크기가 32비트이기 때문입니다. 32비트로 주소값을 표현하면 주소값의 이동 연산이 번에 이루어지기 때문이지요. 뿐만 아니라 표현할 있는 주소의 범위로 4G바이트나 되니 프로그래머 입장에서는 매우 충분하답니다.


1
2
3
4
5
int arr[5= {12345};
int * pArr = arr;
pArr += 1;
cs

코드에서는 arr 가리키고 있는 포인터 pArr 값을 하나 증가시키는 연산을 하고 있습니다. 이러한 연산을 위해서는 pArr 지니고 있는 값을 ALU 이동시켜야 합니다. 최종적인 값의 증가는 ALU 의해 이뤄지기 때문이지요. pArr 지니고 있는 주소값이 32비트라면, 번에 전송이 가능하고, 번에 연산이 가능합니다. 왜냐하면 32비트 데이터의 전송과 연산을 번에 처리할 있는 것이 32비트 시스템이기 때문이지요.

만약에 주소값을 64비트로 표현한다면, pArr 저장하고 있는 64비트 주소값을 번에 나눠서 ALU 전송해야 하고, 최소 이상에 걸쳐서 연산해야만 합니다. 32비트 시스템은 64비트 데이터를 번에 처리하지 못하기 때문이죠. 이는 상당한 속도의 저하로 이어집니다.

그렇다면, 64비트 컴퓨터 환경에서는 포인터가 바이트로 표현될까요? 64비트입니다. 나타낼 있는 주소값의 범위도 2 64승이 되기때문에 64비트에서 표현할 있는 메모리의 크기도 어마어마하게 증가합니다.
  
64비트 메모리 주소


32비트 메모리 주소

32비트와 64비트에서 각 디버깅 결과 포인터가 가리키는 주소값의 크기가 64비트에서는 8바이트, 32비트에서는 4바이트의 크기로 사용되고 있는것을 확인할 수 있습니다.

Q : 내부 메모리에 해당하는 (RAM) 주소가 정해져 있을까요?
A : 메인 메모리인 (RAM) 주소가 붙어있는 것은 아닙니다. 운영체제에서 프로그램 실행을 위해 편의상 붙여놓은 가상의 주소입니다(가상 메모리 주소)


64비트와 32비트 공존문제
프로그램 개발 타입이 일치하지 않은 변수 사이에서의 대입 연산을 종종 시도하는 경우가 있습니다.

1
2
3
4
5
6
7
int main(void)
{
    int arr[10= {0, };
    // 데이터 손실이 발생할 수 있는 위치
    int arrVal = (int)arr;
}
cs

코드에서는 배열이 선언된 주소값을 출력하기 위해 int 변수에 값을 저장하고 있습니다. 이러한 방식의 코드가 32비트 시스템에서는 전혀 문제되지 않습니다. int 자료형도, 포인터도 4바이트로 표현되기 떄문이지요. 그러나 64비트 시스템에서는 문제가 있습니다. 64비트 시스템에서는 포인터를 int, long 4바이트 정수형 데이터로 변환해서는 안됩니다.

64비트 Windows 시스템에서는 LLP64 기본 모델이므로 int 4바이트, 주소값인 포인터는 8바이트로 표현됩니다. 때문에 코드에서 변환 과정에서 데이터 손실이 발생할 있습니다. 64비트 Windows 시스템은 16테라바이트의 메모리 공간을 활용할 있도록 디자인 되었습니다.
따라서 배열 arr 4G 이하의 메모리 영역에 할당되어 4바이트로 주소값 표현이 가능하다면 데이터 손실이 발생하지 않겠지만, 이상의 메모리 영역에 선언된다면 데이터 손실이 발생해서 배열의 정확한 주소값을 확인하지 못하게 됩니다.


그림은 32비트로 4G바이트 이상을 표현할 없다는 것을 보여줍니다.

, 64비트 시스템에서는 포인터가 지니고 있는 주소값을 4바이트 정수형으로 변환하지 말자입니다.