교재: 컴퓨터 시스템 (Computer Systems - A Programmer's Perspective, Randal E. Bryant, David R. O'Hallaron, 제3판, 김형신 옮김, PEARSON, 2016.08.31)
현대의 컴퓨터는 두 개의 값을 갖는 신호로 표현되는 정보를 저장하고 처리한다. 이 낮은 수준의 이진수인 비트는 디지털 혁명의 근원이다. 두 개의 값을 갖는 신호를 저장하고 계산하기 위한 전자회로는 매우 간단하고 안정적이어서 수백만에서 심지어 수천만 회로를 단 한 개의 실리콘 칩에 집적할 수 있을 정도다.
이 장에서 우리는 세 개의 가장 중요한 숫자 표현에 대해 살펴본다. 비부호형 인코딩은 전통적인 이진수 표시를 사용하며, 0 이상의 수를 표시한다. 2의 보수 인코딩은 양수 또는 음수 값을 갖는 부호형 정수를 표시하는 가장 일반적인 방법이다. 부동소수점 인코딩은 2진수 버전의 소수를 표시하기 위한 과학적 표시방법이다. 실제 수의 표시방법을 학습하면서 표시 가능한 값의 범위와 여러 산술연산의 특성을 이해할 수 있다. 이러한 점들에 대해서 이해하게 되면 모든 범위의 숫자들에 있어서도 정확히 동작하고 다양한 컴퓨터, 운영체제, 컴파일러 조합에서도 동일하게 동작하는 프로그램을 작성할 수 있게 된다.
2.1 정보의 저장
메모리에 저장된 각각의 비트들을 접근하는 방식 대신에 대부분의 컴퓨터들은 메모리에서 주소지정이 가능한 최소단위인 8비트 단위의 블록인 바이트를 사용한다. 기계수준의 프로그램은 메모리를 가상메모리라고 하는 거대한 바이트의 배열로 취급한다. 메모리의 각 바이트는 주소라고 하는 고유한 숫자로 식별할 수 있으며, 모든 가능한 주소들의 집합을 가상 주소공간이라고 부른다.
2.1.1 16진수 표시
우리는 비트 패턴을 16진수로 표시하고자 한다. 16진수(간단히 "hex")는 '0'에서 '9'까지의 숫자와 'A'에서 'F'까지의 문자를 사용해서 16개의 가능한 값으로 나타낸다. C언어에서 0x나 0X로 시작하는 숫자 상수들은 16진수로 해석한다. 문자 'A'에서 'F'까지는 대문자나 소문자 모두 사용할 수 있다.
십진수와 16진수 표시 간에 변환을 하기 위해서는 일반적인 경우를 처리하기 위한 곱셈과 나눗셈을 사용해야 한다. 십진수 x를 16진수로 변환하기 위해서 x를 16으로 반복해서 나누고, 몫 q와 나머지 r을 얻는다. 그러면 $x=q \cdot 16+r$ 로 표시된다. 그러고 나면 r을 나타내는 16진수 숫자릴 최소중요숫자(least significant digit)로 사용하고 q에 대해 이 과정을 반복해서 나머지 숫자들을 생성한다. 예를 들어 십진수 314,156은 16진수 0x4cB2c로 표현할 수 있다.
2.1.2 데이터의 크기
모든 컴퓨터는 워드 크기 word size를 규격으로 가지게 되는데, 이것은 포인터의 정규 크기를 표시한다. 하나의 가상주소가 이와 같은 한 개의 워드로 인코딩되기 때문에 이 워드 크기가 결정하는 가장 중요한 시스템 변수가 가상 주소공간의 최대 크기이다. 즉, $w$비트 워드 크기를 갖는 컴퓨터에서 가상주소는 0에서 $2^w - 1$ 범위를 가지며 프로그램은 최대 $2^w$ 바이트에 접근할 수 있게 된다.
C언어에서는 정수와 부동소수점 데이터를 위한 여러 가지 데이터 포맷을 지원한다. 정수 데이터는 0과 음수, 양수를 표시하기 위해서 부호형 signed 정수가 되거나 양수 값만을 나타내는 비부호형 unsigned 정수가 될 수 있다.
2.1.3 주소지정과 바이트 순서
어떤 객체를 나타내는 바이트들을 정렬하는 데는 두 가이 일반적인 관습이 존재한다. 비트 표시 $[x_{w-1}, x_{w-2}, \dots x_1, x_0]$를 갖는 $w$-비트 정수가 있다고 하자. 여기서 $x_{w-1}$은 가장 중요한 비트 most significant bit이고, $x_0$는 가장 덜 중요한 비트이다. 객체를 메모리에 가장 덜 중요한 바이트부터 저장하는 관습을 리트 앤디안 이라고 부르고, 가장 중요한 바이트부터 저장하는 관습을 빅 엔디안이라고 부른다.
2.1.6 부울 Boolean 대수
비트 벡터를 사용하는 유용한 응용으로 유한집합의 표시를 들 수 있다. $i \in A$이면 언제나 $a_i=1$인 비트 벡터 $[a_{w-1}, \dots, a_1, a_0]$를 갖는 부분집합 $A \subseteq \{0, 1, \dots, w-1\}$을 인코딩할 수 있다. 예를 들면, 비트 벡터 $a=[01101001]$은 집합 $A=\{0, 3, 5, 6\}$을 인코딩한다.
2.1.8 C에서의 논리 연산
C에서는 논리 연산의 OR, AND, NOT에 해당하는 논리연산자 ||, &&, !을 제공한다. 이들은 흔히 비트수준 연산과 혼동될 수 있지만, 이들의 동작은 전혀 다르다. 논리 연산은 0이 아닌 인자들을 '참'으로 취급하고, 0은 '거짓'으로 처리한다. 결과가 참인지 거짓인지에 따라 1 또는 0을 리턴한다.
2.1.9 C에서의 쉬프트 연산
C는 비트 패턴을 좌우로 이동시키는 쉬프트 연산 집합을 제공한다. 비트 표시 $[x_{w-1}, x_{w-2}, \dots x_1, x_0]$를 갖는 오퍼랜드 x에 대해 C 식 x<<k는 비트 표시 $[x_{w-k-1}, x_{w-k-2}, \dots, x_0, 0, \dots 0]$을 생성한다. 즉, x는 좌측으로 k비트 이동하고, 중요한 좌측의 k비트가 밀려서 삭제되며 우측에는 k개의 0으로 채워진다. C언어에서는 이와 대응하는 우측 쉬프트 연산 x>>k가 있으며, 이것은 약간의 미묘한 동작을 가지고 있다. 일반적으로 컴퓨터는 두 종류의 우측 쉬프트를 제공한다.
- 논리 우측 쉬프트: 좌측 끝을 k개의 0들로 채워서 $[0, \dots, 0, x_{w-1}, x_{w-2}, \dots x_k]$를 만든다.
- 산술 우측 쉬프트: 좌측 끝을 가장 중요한 비트를 k개 반복해서 채워서 $[x_{w-1}, \dots, x_{w-1}, x_{w-1}, x_{w-2}, \dots x_k]$를 만든다. 이 관습은 약간은 특이한 것 같지만, 이것은 부호형 정수 데이터의 연산에서 유용하게 작용한다.
C표준은 부호현 숫자의 경우에 어떤 타입의 우측 쉬프트가 사용되어야 하는지 명확히 정의하고 있지 않다. 산술 또는 논리 쉬프트 둘 다 사용 가능하다. 실제로는 대부분의 컴파일러/컴퓨터 조합들은 부호형 데이터에 대해서 산순 우측 쉬프트를 사용하고 있으며, 많은 프로그래머들도 이렇게 사용하는 것을 가정하고 있다. 비부호형 데이터에에 대해서 우측 쉬프트는 논리 쉬프트여야 한다.
2.2 정수의 표시
이 절에서는 정수를 인코드하기 위해 사용할 수 있는 두 가지 방법$-$양수만 표시할 수 있는 방법과 음수, 0, 양수 모드를 표시할 수 있는 방법$-$에 대해 설명한다.
2.2.2 비부호형의 인코딩
w비트의 정수형 데이터 타입이 있다고 하자. 전체 벡터를 나타내기 위해서 비트 벡터를 $\vec{x}$로 표시하거나 벡터의 각 비트를
'CS과목 > 시스템소프트웨어' 카테고리의 다른 글
[시스템소프트웨어] 01. 컴퓨터 시스템으로의 여행 (0) | 2025.02.11 |
---|