1. 개요
프로세서를 구성하는 레지스터 중에 하나로 프로세서의 상태나 연산 결과 또는 연산 중에 발생한 상태를 저장하기 위한 특수 목적의 레지스터이다.2. 목적
덧셈, 뺄셈 연산에서 올림과 빌림이 발생됨이나 시프트 연산에서 범위를 초과하는 경우를 나타내기 위해서 쓰인다. 이 사실은 연산 결과로만 알기 어렵기 때문이다.조건부 분기 명령어에서도 쓰이는데 연산 결과의 상태에 따라 코드의 흐름을 다르게 해야 하기 때문이다. 프로세서가 두 값의 대소 비교를 하는 방법은 A에 B를 뺀다. 그리고 그 상태를 기록한다. 빌림이 발생하면 Carry 플래그가 설정되어 작은 값이라는 사실을, 결과가 양수면 Zero 플래그가 해제된다. 만약 Zero 플래그가 설정되었다는 것은 연산 결과가 0이기 때문이고 A와 B가 같은 값이라는 것을 알 수 있다. (1 - 1 = 0이다.)
하지만 위의 나온 대소 비교 방법은 대부분의 경우 통하지 않는데 이를 위해 Overflow 플래그가 존재한다. 오버플로 플래그의 존재 이유는 정수의 비교를 다양한 케이스에서 대응 하기 위해서 이다. A의 값이 음수이고 B의 값이 양수인데 B를 A에 뺐을 때 오버플로가 발생할 정도로 B가 큰 값이라면(혹은 A가 작은 값이라면) 위의 나온 조건으로는 제대로 된 비교가 안된다. 이러한 상황에서는 오버플로 플래그를 조건에 결합해야 한다.
예를 들어, 8비트 프로세서에서 A의 값이 -128, B의 값이 1인 경우, 우리는 이 두 값을 비교했을 때 유부호형 정수 기준으로 A보다 B가 더 크다는 결과를 얻고 싶을 것이다. 하지만 A - B의 결과는 127이므로 빌림이 발생하지도 않았고, 음수인 것도 아니다. 그래서 A가 B보다 더 크다는 잘못된 결과를 얻게 된다. 이때 오버플로 플래그가 조건에 개입하게 되면 오버플로의 발생 또는 결과 값이 음수라는 두 조건이 서로 배타적이거나, 결과 값이 0이 아닌 경우를 A가 B보다 더 큰 상황으로 정의할 수 있는데 위의 -128과 1의 비교에서는 오버플로가 발생했지만 결과값이 양수이므로 조건을 만족하지 않아서 A가 B보다 더 크지 않다라는 결과를 내게 된다.
또한 프로세서의 상태를 나타내기 위해서도 사용되는데 인터럽트를 받아들일지 말지를 결정하는 인터럽트 마스크 비트도 상태 레지스터에 포함된다.
3. 구조
- Carry : 덧셈 또는 뺄셈 연산에 올림 또는 빌림이 발생하거나 시프트 연산에서 범위를 초과하는 경우.
- Half-Carry, Auxilarry Carry : 하위 4비트 올림이 발생할 때.
- Sign, Negative : 연산 결과가 음수일 때.(최상위 비트가 1로 설정된 경우)
- Zero : 연산 결과가 0일때.
- OVerflow : 연산 결과가 양수에서 음수로 바뀌었거나 그 반대인 경우. (x86의 경우) 프로세서마다 다를 수 있다.
- Parity : 연산 결과를 2진수로 나타내었을 때 1로 설정된 비트의 수가 짝수일 때.
- Interrupt Mask Bit : 인터럽트를 거부하거나 허용한다.
4. 상태 레지스터를 사용하는 프로세서들
대부분의 프로세서들은 상태 레지스터를 가지고 있다. 가장 많이 사용되는 x86과 ARM 역시 상태 레지스터를 가지고 있다. x86은 조건부 분기, 조건부 이동 명령어에서 사용되고 ARM의 경우 조건부 분기 명령어가 따로 없는 대신 명령어 세트 자체에 조건부 실행 비트가 있어 거의 모든 명령어를 조건적으로 실행시킬 수 있다. 다만 이 내용은 ARM 32비트 명령어 세트에만 해당되는 내용으로 64비트로 세대 교체한 현재로서는 사용되지 않는 기능이다.일부 RISC 계열 프로세서는 없는 경우가 있다. 대표적으로 MIPS와 RISC-V가 있다.
VLIW 계열 프로세서 중에서는 아이태니엄이 상태 레지스터가 존재하지 않는다.
사실 상태 레지스터가 없는 프로세서들에도 캐리 플래그는 기본적으로 존재하는데(MIPS 프로세서도 캐리 플래그가 기본 사양이다.) 이거 마저 없으면 제대로된 계산이 안된다.[1]
[1]
곱셈은 전용 명령어가 없을 경우 덧셈과 시프트 연산을 이용하도록 되어있다. 시프트 연산을 이용하는 이유는 비트를 테스트하기 위해서인데 시프트 연산을 한번 하면 최상위 비트 또는 최하위 비트가 0인지 1인지 바로 알 수 있다. 하지만 이마저도 없을 경우 추가적인 연산이 발생하게 된다.