컴퓨터를 만듭시다. 어때요~ 참 쉽죠? (13)

나빌레라의 이미지

#13. 빼기. 결국 음수의 더하기

논리회로에서 더하기를 하려면 XOR 게이트와 AND 게이트로 이뤄진 반가산기 두 개를 묶어 만든 전가산기 여러개를 붙여 n비트 가산기를 만들어 처리했다. 더하기를 할 줄 아니 빼기를 하고 싶다. 어떻게 해야 할까? 더하기처럼 별도의 로직 회로를 만들어서 할 수도 있다. 로직 회로를 만들려면 진리표를 만들고 진리표에 맞춰 동작하는 논리 회로를 고민해야 한다.

0 - 0 = 0
1 - 0 = 1
1 - 1 = 0
0 - 1 = -1 ???????

오!이런. 더하기에서는 생각치도 못했던 난관에 봉착했다. 빼기에서는 결과로 음수가 나올 수도 있다. 0과 1밖에 없는 디지털 세상에서 음수를 대체 어떻게 표현하지? 논리 회로에서 빼기를 구현하기 전에 일단 음수를 어떻게 표현해야 하는지부터 해결해야겠다.

우리가 글로 써서 이진수를 표현할 때는 숫자 앞에 부호를 붙여서 +11011011, -0110110001 이렇게 양수, 음수를 표현할 수 있다. 하지만 기본적으로 전기적 1과 전기적 0밖에 없는 디지털 논리 회로로 이뤄진 컴퓨터는 부호를 별도로 표기할 수 있는 방법이 없다. 부호 마져도 0과 1 둘 중 하나로 표현해야 한다.

가장 쉽게 생각할 수 있는 것이 MSB를 부호 표시 비트(Sign Bit)로 사용하는 것이다. 양수는 0, 음수는 1을 붙인다. 8비트 이진수를 기준으로 생각해 보면 +52와 -52를 아래처럼 표현할 수 있다.

0110100 : 0 (양수) 110100 (52) = +52
1110100 : 1 (음수) 110100 (52) = -52

한 비트를 부호 비트로 사용해서 표시할 수 있는 최대 숫자가 127로 줄긴 했지만 대신 -127까지 음수 영역을 표현할 수 있게 되었다. 간단히 음수 표시 문제를 해결한 것인가? 만약 음수를 연산하지 않고 단지 표기만 한다면 해결한 것으로 볼 수도 있다. 하지만 연산을 하게 된다면 어떻게 될까?

양수 1 과 음수 1을 더하면 값은 0이다.

1 + (-1) = 0

반론의 여지가 없는 명백한 사실이다. 하지만 위의 음수 표기법을 사용하면 이 법칙이 동작하지 않는다.

1 = 00000001
-1 = 10000001
1 + (-1) = 00000001 + 10000001 = 100000010 = -2 ??????

슬프지만 이 방법은 산술식에서 제대로 동작하지 않는다. 그리고 또 하나의 문제가 더 있다.

00000000 = +0
10000000 = -0

영(zero, 0)은 음수도 양수도 아니고 그냥 0인데, 위 표기법에서는 양수 0과 음수 0이 각각 존재한다. 인간의 수학 체계가 양수 0과 음수 0의 존재를 각각 인정한 상태에서 발전했다면 문제가 없을지 몰라도 인간의 수학은 천년 넘도록 0은 그냥 0이라는 전제 아래에서 발전했다. 인간이 지금까지 사용해 온 수학 체계 대신 컴퓨터에서 사용되는 수학 체계를 새로 만들지 않는한 위 음수 표기법은 그다지 유용하지 않다. 표기법 하나를 받아들이기 위해 전체 수학 체계를 새로 만드는 것은 배보다 배꼽이 더 큰 격이다.

새로운 방법을 생각해 보자. 새로운 방법에서는 두 가지 조건을 만족해야 한다. 위에서 말한 산술식이 제대로 동작해야 하고 영은 0, 한 개만 존재해야 한다.

일단 산술식이 제대로 동작해야 하므로 익숙한 십진수 산술식이 어떻게 동작하는지 보자.

25 빼기 8를 우리는 어떻게 계산할까? 먼저 숫자의 길이를 맞춰준다. 25 빼기 08이 된다. 그리고 각 자리를 맞춰 빼기를 수행한다. 5에서 8을 빼야한다. 하지만 5가 더 작다. 앞 자리 2에서 1을 빌려와 10에서 8을 빼고 남은 2와 5를 더해 7을 만든다. 2는 아까 1을 빌려줘서 1이 되고 0을 빼서 1이 나온다. 결과는 17이다.

초등학생 수준의 산수다. 하지만 여기에 모든 답이 다 있다. 특히 핵심은 10일 빌려서 8을 빼고 남은 수에 5를 더했던 우리가 아주 익숙하게 처리하는 계산법이다. 이 과정을 바꿔서 쓰면 아래 수식이 된다. 이 과정 속에서 우리는 우리도 모르게 뺄셈을 덧셈으로 바꿔서 처리한다. 즉 음수를 양수로 바꾼다는 말이다.

5 + (10 - 8) = 5 + (9 - 8 + 1)

괄호 안에 뺄셈 기호가 있긴 하지만, 괄호를 하나의 수로 봤을 때 큰 수식은 분명 덧셈이다. 만약에 25 - 8이 아니라 25 - 7이나 25 - 6이라 해도 첫 번째 자리수의 계산법은 그 규칙이 변하지 않는다.

5 + (10 - 7) = 5 + (9 - 7 + 1)
5 + (10 - 6) = 5 + (9 - 6 + 1)

계속 반복되는 부분이 두 군데 있다.

(10 - n)과 (9 - n + 1)이다. 이 둘은 사실상 같은 수식이다. 십진수에서 표현 가능한 최대 숫자는 9다. 그래서 9에 1을 더하면 자리를 넘겨 10이라고 쓰는 것이다. 뭔가 느낌이 오지 않는가? 이야기 하나를 더 해보겠다.

15 빼기 4는 몇 일까? 아마 0.1초도 지나지 않아 계산 끝냈을 것이다. 11이다. 이것을 십진수 두 자리만 계산 가능한 가산기에서 계산한다고 생각해 보자. 십진수 표현은 두 자리만 가능하고 그 이상은 캐리 출력(Carry Out)된다.

15 - 04 = 11

두 자리 십진수에서 표현 가능한 최대 숫자는 99다. 역시 위에서 말한 규칙을 적용하면 이 뺄셈 수식은 덧셈으로 바뀐다.

15 + (99 – 04 + 1) = 15 + 96 = 111

답은 111이 나온다. 그러나 두 자리만 표현 가능한 십진수 가산기라고 가정했으므로 맨 앞 백의 자리 1은 캐리 아웃된다. 그러면 답은 11이다. 오! 우리가 그냥 빼기로 계산했던 결과와 일치한다. 단순히 결과가 일치한다는 사실 뿐 아니라 우리는 더 중요한 사실을 발견했다.

15 – 04 = 11
15 + 96 = (1)11

다시 말하지만 논리 회로는 표현할 수 있는 숫자의 자리수가 한정되어 있기 때문에 111과 11은 두 자리수를 표현할 수 있는 십진수 가산기에서는 동일하게 표시된다. 이 규칙은 이진수에도 그대로 적용된다.

이진수 1101에서 0010을 빼는 식을 생각해 보자.

1101 – 0010 = 1011

http://kldp.org/files/_13_02_1101_sub_0010.png">

앞서 십진수를 계산할 때와 마찬가지로 두 번째 자리에서 값을 빌려왔다. 십진수 계산일 때는 앞 자리에서 1을 빼고 10을 빌려왔지만 이진수기 때문에 앞 자리에서 1을 빼고 2를 빌려왔다. 그렇다면 십진수를 계산할 때의 규칙을 적용해 보자. 4비트 이진수의 최대 값은 1111이다.

1101 + (1111 – 0010 + 1) = 1101 + (1101 + 1) = 1101 + 1110 = (1)1011

4비트만 표기하므로 맨 앞 1은 캐리 아웃된다. 캐리를 제외하면 직접 빼기 계산했을 때와 값이 똑같다. 이것은 두 자리 십진수를 계산할 때 가상의 앞 자리에서 하나를 빌려와 100을 만들어 값을 빼는 식을 두 자리 십진수의 최대 값인 99에서 값을 빼고 1을 더해주는 원리와 일치한다. 즉 네 자리 이진수의 계산에서는 네 자리 이진수보다 한 자리 앞의 수 10000을 만들어 값을 빼서 양수로 만드는데 그 식을 네 자리 이진수의 최대 값인 1111에서 값을 빼고 1을 더하는 식으로 고친것이다.

그리고 잘 보면 이진수에서는 음수를 양수로 바꾸는 위 식을 아주 간단한 규칙으로 수행함을 알 수 있다. 0은 1로 바꾸고 1은 0으로 바꾼다음 마지막에 1을 더한다. 1111에서 어떤 이진수를 빼면 당연히 1은 0으로 바뀌고 0은 1로 바뀐다. 그리고 마지막에 1을 더한다.

이렇게 n비트 이진수를 n비트의 최대 값에서 뺀수. 즉 0과 1을 그대로 바꾼 수를 1의 보수라고 부르고 n비트 이진수를 (n+1)비트에서 한 자리 빌려온 값에서 뺀수. 즉 1의 보수에서 1을 더한 수를 2의 보수라고 부른다. 마찬가지로 십진수에서도 9의 보수, 10의 보수라고 부른다.

모든 이진수 연산에서 뺄셈은 2의 보수를 이용해 덧셈으로 바꿀 수 있다. 물론 그 경우 캐리가 발생한다. 그래서 유효 자리수만 인정하고 캐리는 무시한다.

범위를 줄이기 위해 4비트 이진수의 숫자와 2의 보수를 모두 나열해 보겠다. 순서대로 이진수, 2의 보수, 십진수 값이다.

0000 0000 → 0, 0
0001 1111 → 1, -1
0010 1110 → 2, -2
0011 1101 → 3, -3
0100 1100 → 4, -4
0101 1011 → 5, -5
0110 1010 → 6, -6
0111 1001 → 7, -7

1000 1000 → 8, -8
1001 0111 → 9, -9
1010 0110 → 10, -10
1011 0101 → 11, -11
1100 0100 → 12, -12
1101 0011 → 13, -13
1110 0010 → 14, -14
1111 0001 → 15, -15

위 숫자에서 내가 빨간색으로 표시한 숫자들만 이어서 보면 연속된 이진수 숫자이지만 4비트로 표현가능한 16개 숫자중 반으로 나누어 0, 양수 1~7, 음수 -1 ~ -8까지 표현 할 수 있음을 알 수 있다. 또한 양수 부분과 마찬가지로 음수 부분도 이진수가 1씩 늘어 날 수록 2의 보수로 연결되는 음수도 1씩 늘어난다.

1001 → -7
1010 → -6

2의 보수안에서도 수의 법칙은 잘 지켜진다는 말이다. 게다가 -1을 뜻하는 1111 + 1은 0이다. 실제로도 -1 + 1 = 0이다. 영도 유일하게 존재하고 산술 체계도 제대로 동작한다. 그리고 음수 부분을 보면 MSB가 모두 1이다. 2의 보수로 음수를 표현하면서 자연스럽게 MSB에 1이 생겼다. 이렇게 되면 맨처음 이야기했던 부호 비트의 효과도 볼 수 있게된다.

실제 우리가 사용하는 컴퓨터에서 음수의 표시를 2의 보수로 하고 있다. 그리고 이 이야기를 읽기 전에 이미 여러분들은 컴퓨터에서 음수의 표기를 2의 보수로 하고 있다는 사실을 알고 있을 것이다. 하지만 그 원리가 이 이야기처럼 우리가 초등학교 때 배웠던 뺄셈 규칙에 있다는 사실은 처음 접한 분들도 꽤 있었을 것이다. 막연히 외우기만 했던 2의 보수가 사실은 저런 원리로 적용되고 있는 것이다.

음수를 2의 보수로 표현 가능하게 되면서 우리가 만들고 있는 컴퓨터 역시 뺄셈을 ‘음수를 더하는 계산’으로 처리할 수 있게 되었다. 그러면 지난 번까지 만들었던 가산기를 그대로 이용할 수 있다. 단지 2의 보수를 만들어 주는 회로를 가산기 입력전에 넣어주어서 뺄셈을 하고 싶을 경우 2의 보수 회로를 동작시켜 주면 된다. 재미있지 않은가!

File attachments: 
첨부파일 크기
Image icon _13_02_1101_sub_0010.png4.91 KB
Image icon _13_01_25_sub_8.png6.02 KB

댓글

nuwool의 이미지

학부시절에 들었던.. 무턱대고 외웠던 내용들이.. 자연스럽게 머릿속에서 정리되어 자리 잡아가는 기분이네요...
알기 쉬운 이해하기 쉬운 설명 정말 감사드립니다.
책으로 나오면 꼭 사서 보고 싶네요..

댓글 달기

Filtered HTML

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

BBCode

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param>
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

Textile

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • You can use Textile markup to format text.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Markdown

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • Quick Tips:
    • Two or more spaces at a line's end = Line break
    • Double returns = Paragraph
    • *Single asterisks* or _single underscores_ = Emphasis
    • **Double** or __double__ = Strong
    • This is [a link](http://the.link.example.com "The optional title text")
    For complete details on the Markdown syntax, see the Markdown documentation and Markdown Extra documentation for tables, footnotes, and more.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Plain text

  • HTML 태그를 사용할 수 없습니다.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 줄과 단락은 자동으로 분리됩니다.
댓글 첨부 파일
이 댓글에 이미지나 파일을 업로드 합니다.
파일 크기는 8 MB보다 작아야 합니다.
허용할 파일 형식: txt pdf doc xls gif jpg jpeg mp3 png rar zip.
CAPTCHA
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.