반도체

[MCU강의⑤] CPU 실행방법… 덧셈·뺄셈·곱셈·나눗셈 어떻게?

한주엽

<편집자 주> 디지털데일리는 총 11회에 걸쳐 마이크로컨트롤러유닛(MCU)의 면면을 파헤치는 해설 기사를 게재합니다. MCU는 다양한 전자제품에 탑재되는 핵심 반도체 가운데 하나입니다. 글 싣는 순서는 다음과 같습니다. ①MCU란 무엇인가? ②MCU의 내부 구성 ③CPU란 무엇인가? ④MCU 소프트웨어 개발 ⑤CPU 실행방법 ⑥ALU의 구성 ⑦MCU용 언어 ⑧호스트 PC를 타겟 보드에 연결하는 툴 선택하기 ⑨범용 IO ⑩MCU 개발에 사용되는 소프트웨어 개요 ⑪MCU의 팹 공정.

MCU는 다양한 산술 연산을 수행할 수 있으나 사실상 덧셈만 가능하다. 가령 뺄셈, 곱셈, 나눗셈을 수행하려면 덧셈과 논리 반전(inversion) 및 시프팅(shifting) 연산을 결합한다. 다음과 같이 설명할 수 있다.

◆덧셈

그림 1. 이진수 덧셈
그림 1. 이진수 덧셈

가장 단순한 산술 연산인 덧셈을 살펴보자. 이진수 덧셈은 십진수 덧셈과 크게 다르지 않다. 특정 열(column)의 수를 더해서 2가 될 경우, 왼쪽 열로 1을 ‘자리올림(carried)’ 한다. 그림 1은 두 이진수 [0, 1, 1, 0]와 [0, 0, 1, 1]를 더한 예를 보여준다(이진수는 [ ]로 표현함). 참고로 왼쪽 열로 1을 더하는 것을 ‘자리올림(carrying)’ 이라 하고, 왼쪽 열에서 1을 제하는 것을 ‘자리내림(borrowing)’으로 표현한다.

◆뺄셈

뺄셈을 보자. MCU는 뺄셈을 직접 수행할 수 없기 때문에 보수(complement)를 이용해서 간접적으로 계산한다. 그렇다면 보수란 무엇인가? 숫자 y의 보수 x란 x + y의 결과가 자리올림 되는 최소의 x값을 말한다. 즉, x와 y가 한자리의 십진수인 경우, 보수는 x+y=10이 되는 x 값을 말한다. 이진수의 경우 x+y=2가 될 x값을 뜻한다(예, [1, 0]).

예를 들어, 십진수에서 6의 보수는 4이며, 3의 보수는 7이다. 이진수의 경우 [1]의 보수는 [1]이 되는데, 이는 [1]+[1]=[1, 0] (첫 번째 열에서 두 번째 열로 1 자리올림) 이기 때문이다. 이와 같이 [1, 1, 0, 1]의 보수는 [0, 0, 1, 1]인데 이는 [1, 1, 0, 1]+[0, 0, 1, 1]=[1, 0, 0, 0, 0](두 수의 합이 2가 될 때마다 왼쪽 열로 1 자리올림)이기 때문이다.

그렇다면, 뺄셈에서 보수가 어떻게 사용될까? 우선 보수에 임의의 수를 더해보자. 쉬운 이해를 위해 십진수를 사용한다. 숫자 9(피감수)에서 숫자 6(감수)를 빼기 위해 보수를 사용하는 방법을 살펴보자. 감수의 보수는 4이고 이를 피감수에 더하면 다음과 같다.

9+4=13

여기서 올림수를 제하면 3이 남는데 이는 9에서 6을 뺐을 때의 결과이다.

9-6=3

이는 곧, 감수의 보수와 피감수를 더한 후 높은 자리 수를 제하면 사실상 뺄셈을 수행하게 된다는 뜻이다.

다음으로 이진수를 이용하겠다. [1, 1, 1, 1](15)에서 [1, 1, 0, 1](13)을 빼기 위해서는 [1, 1, 0, 1]의 보수가 필요한데, 이는 [0, 0, 1, 1]이다. 보수를 피감수에 더한 결과는 다음과 같다.

[1,1,1,1](15)+[0,0,1,1](3)=[1,0,0,1,0](18)

그 후, 여기서 올림수를 제하고 마지막 4자리를 보면 [0, 0, 1, 0](2)다.

[1,1,1,1](15)-[0,0,1,1](13)=[0,0,1,0](2)

이는 곧, 이진수의 경우에도 피감수를 감수의 보수에 더하면 사실상 뺄셈을 수행하게 된다는 뜻이다. 이와 같이 보수와 덧셈을 이용해 뺄셈을 수행할 수 있으나 보수를 구하기 위한 계산이 먼저 선행돼야 한다.

그림 2. 이진수 보수 산출
그림 2. 이진수 보수 산출

MCU는 이진수 보수를 쉽게 산출할 수 있다. 이는 각 자릿수를 반전시키고(즉, [0] → [1] 또는 [1] → [0]) 마지막에 [1]을 더함으로써 가능하다. 그 예는 그림 2와 같다. [1, 1, 0, 1]의 보수를 구하기 위해 각 자릿수를 [0, 0, 1, 0]으로 반전시킨 후, 끝에 [1]을 더하면 [0, 0, 1, 1]이 된다. MCU는 역(inverse)의 논리 연산을 통해 이진수의 각 자릿수를 쉽게 반전시킬 수 있다. [1]을 더하기 위한 회로는 증가기(incrementer)로 불리며, 간단하게 회로를 추가해 구현할 수 있다.

다른 방법으로도 보수를 산출할 수 있다. 가장 높은 자리부터 최우측 [1] 앞까지의 모든 [1]과 [0]을 반전시키고, 나머지(최우측 [1] 포함)는 그대로 두는 것이다. 예를 들어, [1, 1, 0, 1]의 보수를 구하려면 최우측 [1] 앞의 높은 자리([1, 1, 0])를 반전시키는데 그 결과는 [0, 0, 1, 1]이 된다. 이진수 [1, 0, 1, 0]의 경우 높은 자리의 [1, 0] 반전 후 [1, 0](최우측 [1] 및 그 다음 자릿수)은 그대로 둔다. 그 결과 보수는 [0, 1, 1, 0]이 된다. 그러나 MCU에서 최우측 [1]을 판단하기 어렵기 때문에 일반적으로 모든 자릿수(즉, 모든 비트) 반전 후 [1]을 더하는 첫번째 보수 산출 방법을 사용한다.

◆곱셈

그렇다면 곱셈은 어떻게 해야 할까? 기본 원리에 따라 가장 단순하면서 쉬운 곱셈법은 피승수(다른 수로 곱해지는 수)에 피승수를 승수(곱하는 수) 횟수만큼 더하는 것이다. 이 방법은 가산기(adder) 및 계수기(counter) 로 구현할 수 있다. 1-2 자릿수의 간단한 승수 및 피승수를 곱하는 경우엔 이 방법을 쉽게 사용할 수 있으나 32비트(즉, 32자리) 수를 곱할 경우 2의 32제곱(4,294,967,296)회까지 덧셈을 수행해야 할 수도 있다. MCU의 계산속도가 빠르긴 하지만 그 정도 규모의 수 계산은 비현실적이다.

그림 3. 이진수 곱셈의 예
그림 3. 이진수 곱셈의 예

긴 곱셈(long multiplication)을 이용해 이진수를 곱셈했던 때를 생각해 보자. 그림 3은 그와 같은 방식을 이용한 [1, 0, 1, 0]x[1, 0] 산출법을 보여준다. 여기서 (1)은 피승수x승수 1열의 결과이며 (2)는 피승수x승수 2열의 결과다. (1)에서 승수 1열의 수는 [0]이기 때문에 곱은 [0, 0, 0, 0]이 된다. (2)에서는 승수 2열의 숫자가 [1]이기 때문에 그 곱은 피승수를 왼쪽으로 한자리 옮긴 것이 된다(즉, 승수의 2열과 맞춤). 이진수 계산은 [1]과 [0]만을 사용하기 때문에 상당히 단순하다. 기본적으로 승수의 [1]마다 피승수를 왼쪽으로 옮겨 최우측 수가 승수의 관련 [1]과 맞도록 한 후 모든 열을 더한다. 이와 같이 자리를 옮기는 것을 ‘시프팅(shifting)’이라고 부르며 이를 수행하기 위한 연산 유닛을 ‘시프터(shifter)’라고 한다. 인버터(inverter)와 마찬가지로 시프터도 쉽게 만들 수 있다. 따라서 시프터와 가산기만 있다면 MCU로 곱셈을 수행할 수 있다.

가장 단순한 곱셈 회로(또는 최소필요회로)는 1비트(한자릿수) 시프터와 가산기로 구성된다. 32비트(32자리) 이진수 곱셈 또한 시프트 32회, 덧셈 최대 32회를 수행함으로써 가능하다. 덧셈을 4,294,967,296회까지 할 필요가 없는 것이다.

◆나눗셈

기본 원리에 따라 가장 단순하면서 쉬운 나눗셈법은 몫이 [1] 미만이 될 때까지 피제수(나누어지는 수)에서 제수(나누는 수)를 계속 뺀 후 뺀 횟수를 세는 것이다. 그러나 곱셈과 같이 32비트 피제수의 경우 뺄셈을 최대 4,294,967,296회 수행해야 하므로 비현실적이다. 더욱이, 곱셈과정에서는 덧셈을 일부 줄일 수 있지만 나눗셈은 뺄셈을 줄일 수 없기 때문에 나눗셈이 더 어려울 수 있다.

그림 4. 이진수 나눗셈 예
그림 4. 이진수 나눗셈 예

긴 나눗셈(long division)을 이용해 계산해보겠다. 그림 4는 긴 나눗셈을 이용해 [0, 1, 1, 0]을 [0, 1, 1]로 나누는 것을 보여준다. 제수가 세자리 수이므로 우선 피제수의 첫 세 자리(즉, [0, 1, 1])를 제수(즉, [0, 1, 1])로 나눌 수 있다. 십진수와 달리, 이진수는 [1]과 [0]으로만 구성되기 때문에 제수를 피제수의 첫 세 자리에서 빼면 된다. 그 후, 그 차의 다음 세 자리 수에서 제수를 빼고 피제수의 마지막 자리까지 이를 반복한다. 그 결과 몫과 나머지를 얻게 된다. 그림 4에서 피제수는 4자리이고 제수는 3자리이다. 그러므로 뺄셈을 두 번만 해도 충분하다. 제수와 피제수의 자릿수가 크게 다를 경우, 시프트 및 뺄셈 횟수가 증가하게 되고 그 결과, 계산 횟수도 증가하게 된다. 그러나 제수 및 피제수의 자릿수가 같다면 뺄셈 한번으로 나눗셈을 할 수 있기 때문에 계산 속도가 빨라진다. 이를 고려할 때, MCU는 시프터와 감산기(subtractor)만 있으면 이와 같은 알고리즘을 이용해 나눗셈을 수행할 수 있다.

ARM의 코어텍스 M3 MCU 코어는 감산기 하드웨어를 내장하고 있다. 나눗셈 계산 시간은 2-12사이클에 이르며(1 사이클=계산 1회 수행 시간), 나눗셈에 필요한 사이클 수는 제수 및 피제수의 자릿수에 따라 달라진다. 제수와 피제수의 자릿수가 같다면 2 사이클로 계산을 완료할 수 있으나 자릿수가 다른 경우 최대 12 사이클이 필요할 수 있다.

글 : 마사루 스가이(ST마이크로 MMS그룹)

한주엽
webmaster@ddaily.co.kr
기자의 전체기사 보기 기자의 전체기사 보기
디지털데일리가 직접 편집한 뉴스 채널