overflow flag와 carry flag의 비교
ARM 아키텍처에는 16개의 레지스터와 함께 cpsr(current program status register)이라고 하는 레지스터가 존재한다.
cpsr은 다음과 같은 구조인데, 이번 포스팅에서는 이 cpsr에서의 flags 부분에서 overflow, carry flag를 비교해볼 것이다.
보통 overflow 를 흘러넘치다라는 표현으로 받아들이고, overflow랑 carry를 혼동하는 경우가 많다.
나같은 경우, 정확하기 이해하기 전에는 이 두 개념을 완전히 서로 반대로 이해하고 있었는데,
예를 들어 4-bit 연산을 한다고 했을 때,
1) 1000 + 1000 = 10000 (여기서 맨 앞에 있는 1은 사라지게 됨)
이런 경우 overflow가 되는 것이라고 생각했다. (왜냐하면 4개의 비트에서 흘러넘쳤으니깐)
하지만 이 경우에는 carry flag가 set되는 것이다.
즉, carry flag는 최상단 비트에서 캐리가 생겼을 때 set 된다!
반면,
2) 0111 + 0001 = 1000
그리고 이 경우에는 overflow flag가 set되는 것이다.
왜냐하면, 이들이 signed expression이라고 가정했을 때, 7+1 = 8이 나와야 하지만, -8이 나왔기 때문이다. (overflow로 인한 잘못된 결과)
즉, 부호가 있는 연산에서 최대 표현 숫자를 넘어서서 오버플로우가 난 경우 overflow flag가 set된다!
(같은 부호를 더했을 때 다른 부호가 나오는 것으로도 오버플로우를 인지할 수 있다.)
따라서, signed 에서만 overflow flag가 의미 있고,
unsigned 에서만 carry flag가 의미가 있는 것이다.
하지만 주의해야 할 점은 CPU는 signed/unsigned와 같은 의미를 모른다.
따라서, 내가 지금 무슨 연산을 하고 있던 간에 overflow flag가 set되야 할 때, carry flag가 set되야 할 때는 독립적인 사건이다.
즉, 1000 + 1000 = 10000과 같은 상황에서는 두 플래그가 모두 셋이 될 것이다.
왜냐하면, 부호가 있다고 생각하든 없다고 생각하든, 최상단 비트에서 carry가 생겼으며,
두개의 입력값 모두 최상단 비트는 1인데 결과는 최상단 비트가 0이 되었으므로 오버플로우 플래그도 세팅이 되는 것이다.
즉, 내가 지금 signed 연산을 하고 있더라도, carry flag는 의미는 없지만, set될 수도 있고 아닐 수도 있는 것이다.
왜 의미가 없냐 하면, 어차피 signed연산을 하는 시점에서는 최상단 비트는 오로지 부호의 역할만 하므로 그 이후 캐리가 생기고 말고는 의미가 없는 것이다.