봉황대 in CS

[Chapter 3. 컴퓨터 연산] 덧셈과 뺄셈, 오버플로우 탐지와 처리 본문

Computer Science & Engineering/Computer Architecture

[Chapter 3. 컴퓨터 연산] 덧셈과 뺄셈, 오버플로우 탐지와 처리

등 긁는 봉황대 2022. 8. 24. 22:01

* 본 글은 '컴퓨터 구조 및 설계: 하드웨어/소프트웨어 인터페이스(Computer Organization and Design: The Hardware/Software Interface) 5th edition'의 내용과 2021학년도 1학기에 수강한 '컴퓨터 구조' 과목 강의 내용을 함께 정리하여 작성하였습니다.

 

32비트 2의 보수 표현

앞서 2의 보수 표현법을 다룬 적이 있다.

2022.08.17 - [Computer Science/Computer Architecture] - [Chapter 2. 명령어: 컴퓨터 언어] 이진수와 2의 보수 표현법, 부호확장, 16진수

 

컴퓨터에선 32비트의 수를 연산을 할 것이기 때문에, 32비트의 수도 2의 보수로 표현할 수 있어야 한다.

32비트의 부호있는 수의 표현은 다음과 같다.

 

 

32비트에서도 마찬가지로 모든 비트를 반대로 바꾸고, 1을 더하면 그 수의 2의 보수가 된다.

 

MIPS Arithmetic Logic Unit (ALU)

MIPS에서는 산술 연산 혹은 논리 연산을 가진 명령어가 매우 많다.

add, addi, addiu, addu
sub, subu
mult, multu, div, divu
sqrt

and, andi, nor, or, ori, xor, xori
beq, bne, slt, slti, sltiu, sltu

 

이러한 명령어들의 연산은 누가 수행하는 것일까?

바로 산술 연산 장치(Arithmetic Logic Unit, ALU)가 한다.

 

 

덧셈과 뺄셈


32비트의 이진수의 덧셈과 뺄셈은 ALU에서 어떻게 이루어질까?

 

우리가 10진수 덧셈을 할 때와 똑같다.

 

오른쪽에서 왼쪽으로 한 비트씩 더하고, 올림수는 바로 왼쪽 자리로 보낸다.

즉, 이진수에서는 최대 표현 가능한 수는 1이므로 1+1이 되면 1이 올림수가 되어 10이 된다.

 

예를 들어, 000111(7)과 000110(6)을 더한다고 생각해보자.

 

 

사람이 손으로 계산하는 것과 똑같이 올림(carry)을 진행해주면 된다.

 

 

그렇다면 뺄셈은 어떻게 해야할까?

 

2의 보수 표현법을 사용하여 뺄 값의 부호를 바꾸어 더해주면 된다.

 

예를 들어, 7-6을 한다고 해보자.

6의 2의 보수는 111010이므로, 000111(7)과 111010(-6)을 더해주면

맨 앞의 수는 버림 되어 결과는 000001 즉, 1이 될 것이다.

 

오버플로우 탐지와 처리


컴퓨터는 32비트의 수까지만 표현이 가능한데, 수끼리 더하여 32비트로는 표현할 수 없는 수가 나오면 어떻게 해야할까?

 

이렇게 컴퓨터에서 하드웨어가 표현할 수 있는 수의 범위를 넘어서서

표현하고 싶었던 수가 나오지 못하는 것을 오버플로우(overflow)라고 한다.

 

오버플로우는 부호가 다른 수를 더했을 때는 절대 일어나지 않고,

부호가 같은 수를 서로 더했을 때 일어난다.

 

덧셈과 뺄셈에서의 오버플로우 발생 조건

 

그렇다면 이러한 오버플로우가 일어났는지 일어나지 않았는지는 어떻게 탐지할 수 있을까?

 

같은 부호를 가진 수를 더했을 때 sign bit(MSB)가 달라졌다면 오버플로우가 발생했다는 것이다.

 

아래와 같이 연산을 한다고 해보자.

 

오버플로우 감지 식을 나타내면 다음과 같다.

 

 

만약 sign bit(MSB)에 대해서 carry in을 Cn-1, carry out을 Cn이라고 표현한다면

* carry in : MSB로 올라오는 올림수

* carry out : MSB 연산으로 인해 발생한 올림수

 

오버플로우 감지 식은 이렇게도 나타낼 수 있다. (xor 연산)

 

 

즉, MSB에 들어오는 carry bit과 나가는 carry bit이 다를 때 오버플로우가 나는 것을 감지할 수 있다.

 


컴퓨터 설계자는 연산 오버플로우를 어떻게 처리할지 결정해야 한다.

 

어떤 경우에는 오버플로우를 무시하고, 다른 경우에는 이를 인식하는 방법을 제공해야 한다.

 

 

MIPS는 이 두가지 선택을 지원하기 위해 두가지 산술 명령어를 제공한다.

 

1.  아래의 명령어들은 오버플로우가 발생하면 예외(exception)을 발생시킨다.

= 인터럽트(interrupt) 발생

add	# add
addi	# add immediate
sub	# subtract

 

2. 아래의 명령어들은 오버플로우가 발생해도 예외를 발생시키지 않고 무시한다.

addu	# add unsigned
addiu	# add immediate unsigned
subu	# subtract unsigned

 

C에서는 오버플로우를 무시하기 때문에

MIPS C 컴파일러는 변수의 형에 관계 없이 언제나 부호 없는 버전인 addu, addiu, subu 명령어를 생성한다.

 

그러나 MIPS Fortan 컴파일러는 피연산자의 형(type)에 따라 적절한 산술 명령어를 생성한다.

 

 

만약 오버플로우가 발생하여 예외(인터럽트)가 발생하면

EPC(exception program counter)라고 불리는 레지스터에 오버플로우가 발생한 명령어의 주소가 저장되고,

컴퓨터는 적절한 처리를 하기위해서 해당 루틴으로 점프한다.

 

이렇게 명령어 주소를 기억해서 인터럽트 처리 루틴을 끝낸 후 인터럽트가 걸린 명령어로 되돌아갈 수 있게 한다.

 

 

반응형
Comments