-
[컴구] #04. MIPS에서의 사칙 연산2023-2학기/컴퓨터구조 2023. 10. 18. 22:33
이번 글에서는 컴퓨터 내부에서 사칙 연산이 실제로 어떻게 계산되는지에 대해 좀 더 자세히 알아보도록 하겠습니다.
덧셈과 뺄셈
덧셈, 뺄셈은 컴퓨터와 사람의 계산 방법이 크게 다르지 않습니다. 손으로 계산할 때처럼 가장 오른쪽에 있는 수부터 더하고, 올림이 발생하면 올려주고, 왼쪽으로 계산을 이어나갑니다.
저희가 주목해야 할 부분은 바로 Overflow(오버플로우)입니다. 계산의 결과가 사용 가능한 하드웨어 (이 경우에서는 32비트겠죠)로 표현할 수 없는 경우입니다.
부호가 있는 수의 경우에는 오버플로우가 일어났음을 쉽게 감지할 수 있습니다. 두 양수를 더했는데 그 결과가 음수가 되었다던가, 두 음수를 더했는데 결과가 양수가 되었다던가.. 이런 경우는 부호 비트로 올림이 진행된 것이므로 오버플로우가 일어났다는 사실을 알 수 있습니다. 음수에서 양수를 뺐는데 양수가 되거나, 양수에서 음수를 뺐는데 음수가 되거나, 하는 경우도 오버플로우가 일어났다고 할 수 있겠죠.
부호가 없는 수의 경우는 이런 방식으로 오버플로우를 감지할 수 없습니다. 그래서 MIPS는 2가지 산술 명령어를 지원합니다. add, addi, sub 명령어는 오버플로우가 발생할 경우, 이를 자체적으로 감지하여 예외를 발생시킵니다. 그러나, addu, addiu, subu 명령어는 오버플로우가 발생해도 예외를 발생시키지 않습니다.
C와 같이 오버플로우를 무시하는 프로그래밍 언어를 컴파일 할컴파일할 때, MIPS는 addu 등의 명령어를 사용해 컴파일을 합니다. 다른 프로그래밍 언어를 컴파일할 때는 add 등의 명령어를 사용하겠죠.
곱셈
먼저 용어 정리를 하고 가겠습니다. 곱하는 첫번째 수를 Multiplicand, 두번째 수를 Multiplier라고 하며 그 결과를 Product라고 부르겠습니다.
사람이 곱셈을 진행할 때, 위와 같은 프로세스로 계산을 하게 됩니다. Multiplier의 자릿수가 1이면 Multiplicand를 해당 위치에 적고, Multiplier의 자릿수가 0이면 0을 적습니다. 그리고 그 수들을 전부 더해주면 Product가 계산됩니다.
이와 같은 설계를 컴퓨터로 옮긴 것을 그림으로 그려보면 아래와 같습니다.
Multiplicand와 Product는 64비트 레지스터에, Multiplier는 32비트 레지스터에 저장되어 있습니다. 매 단계마다 Multiplicand를 왼쪽으로 한 자리씩 이동시킵니다. 그리고 오른쪽 아래 Control이 보이죠? 이 Control은 Multiplier에서 비트를 받아 Multiplicand를 Product에 더할 것인지 말 것인지를 결정합니다. 실제 덧셈 연산은 64-bit ALU가 수행합니다.
위 과정을 도표로 나타내면 아래와 같습니다. 여기에서 알 수 있듯, 이 곱셈 연산에서 한번의 단계에서 3개의 클럭 사이클이 사용됩니다.
이 하드웨어는 이전에 사용했던 알고리즘을 살짝 수정한 것입니다. Multiplier가 사라지고, Multiplicand 레지스터는 32비트로 변경되었습니다. Multiplier는 Product 레지스터의 하위 32비트에 저장되어 있는데요, 매 단계에서 Product 전체가 왼쪽으로 한 자리수 이동되고 자리이동을 하면서 사라지는 비트를 Control이 감지하여 만약 그 비트가 1일 경우 Multiplicand를 Product의 상위 16비트에 더하는 연산을 수행합니다.
이런 방식을 사용하게 되면 매 단계에서 하나의 클럭 사이클만을 사용하도록 만들 수 있습니다.
32비트 수와 32비트 수를 곱하면 최대 64비트 수까지 등장할 수 있습니다. 그래서 MIPS는 64비트의 Product를 저장할 수 있는 한 쌍의 32비트 레지스터 Hi, Lo를 별도로 지원합니다.
mult t0, t1
이렇게 mult 명령어를 작성하면 프로그램은 t0에 저장된 수와 t1에 저장된 수를 곱하여 그 결과의 상위 16비트를 Hi 레지스터, 하위 16비트를 Lo 레지스터에 저장합니다.mflo s0
mfhi s1
이렇게 mflo, mfhi 명령어를 사용하여 Hi, Lo 레지스터에 저장된 값을 레지스터로 불러올 수 있습니다. mult는 부호 있는 수의 곱셈을 담당하는 명령어이고, 부호 없는 수의 곱셈은 multu 명령어를 사용해 계산할 수 있습니다.나눗셈
나눗셈은 나누어지는 수인 Dividend, 나누는 수인 Divisor로 구성되며, 그 결과는 몫인 Quotient와 나머지 Remainder로 나옵니다. 초등학생 때 나눗셈을 배울 때, 얼마나 큰 수를 Dividend에서 뺄 수 있는지를 바탕으로 나눗셈을 배웁니다. 이 알고리즘을 그대로 하드웨어에 구현하면 아래와 같습니다.
Divisor는 64비트 레지스터의 상위 32비트에 저장되어, 한 단계가 진행될 때마다 왼쪽으로 한 자리씩 옮겨갑니다. Divisor와 Dividend의 차이를 계산하여 결과가 양수이면 몫에 1을 넣고, 음수이면 다음 단계로 진행합니다. 이를 그림으로 옮기면 아래와 같습니다.
이 그림에는 제가 설명하지 않은 부분이 있는데, 가장 첫 단계에서 Dividend가 Divisor보다 큰지 작은 지를 계산하는 부분이 포함되어 있으니 참고하시면 좋을 듯합니다.
곱셈과 같이, 나눗셈도 같은 방법을 사용하여 과정을 단순화할 수 있습니다.
MIPS에서 나눗셈을 담당하는 명령어는 div와 divu입니다. 이 역시 Hi와 Lo 레지스터를 사용하는데, 계산 결과의 몫이 Lo에, 나머지가 Hi에 저장됩니다. 역시 mflo, mfhi 명령어를 이용해 저장된 값을 불러올 수 있습니다.
감사합니다.
이 글은 컴퓨터공학과 학부생이 개인 공부 목적으로 작성한 글이므로, 부정확하거나 틀린 내용이 있을 수 있으니 참고용으로만 봐주시면 좋겠습니다. 레퍼런스 및 글에 대한 기본적인 정보는 이 글을 참고해 주세요.
'2023-2학기 > 컴퓨터구조' 카테고리의 다른 글
[컴구] #03. Procedure (1) 2023.10.18 [컴구] #02. MIPS 명령어 (0) 2023.10.09 [컴구] #01. Introduction (1) 2023.10.09 [컴구] #00. Course Information (1) 2023.10.09