CPU 작업 (2)
Source: Dev.to
CPU가 루프와 조건문을 구현하는 방법
CPU는 숫자에 대한 산술 연산만 수행하지만, 분기 명령이라는 특수 명령을 통해 실행 흐름을 바꾸어 루프와 조건 분기를 실행할 수 있습니다.
조건 점프 (JZ)
전형적인 조건 점프 명령은 JZ(jump if zero)입니다. 특정 플래그(제로 플래그)가 설정되어 있을 때 라벨이 붙은 주소로 제어를 이동합니다.
LOAD A, 1
LOAD B, 1
CMP A, B ; compare A and B
JZ exit ; jump to `exit` if the comparison result is zero
STOREM A, 0 ; store register A to memory
exit:
HALT
JZ가 확인하는 것은?
JZ는 라벨 자체를 검사하지 않습니다. 앞선 CMP 명령에 의해 설정된 **Zero 플래그(Z)**를 확인합니다. 플래그가 참(1)이면 CPU는 라벨이 표시된 주소로 점프합니다.
CMP에 의해 업데이트되는 플래그
CMP(compare) 명령은 두 피연산자를 뺀 결과를 저장하지 않고 상태 플래그만 업데이트합니다.
| 플래그 | 의미 |
|---|---|
| Z (Zero) | 뺄셈 결과가 0이면 1로 설정 |
| N (Negative) | 결과가 음수이면 1로 설정 |
실제 CPU에서는 이러한 플래그가 상태/플래그 레지스터에 존재하고, 시뮬레이션에서는 간단한 구조체에 저장될 수 있습니다.
루프 예시
조건 점프(JZ)와 무조건 점프(JMP)를 조합하여 루프를 만들 수 있습니다.
LOAD A, 4
LOAD B, 1
LOAD C, 1
loop:
SUB A, B ; A = A - B
CMP A, C
JZ exit ; if A == C, exit loop
JMP loop ; otherwise repeat
exit:
HALT
JZ는 조건부 종료를 수행합니다.JMP는 무조건 루프 시작으로 다시 점프합니다.
제로 플래그가 설정되지 않으면 실행은 JMP로 넘어가며, 이는 항상 loop 라벨로 제어를 반환합니다.
CMP 구현 (시뮬레이션)
// Subtract operandB from operandA and set flags
int temp = reg.r[inst.operandA] - reg.r[inst.operandB];
flag.zero = (temp == 0);
flag.negative = (temp < 0);
programCounter++; // advance to next instruction
핵심 규칙: CMP는 레지스터나 메모리를 변경해서는 안 되며, 오직 플래그만 업데이트해야 합니다.
기타 점프 명령
CPU 설계에 따라 다음과 같은 추가 조건 점프가 제공될 수 있습니다.
JG– greater일 때 점프 (Z = 0 그리고 N = 0)JL– less일 때 점프 (N = 1)JNZ– not zero일 때 점프 (Z = 0)
이들 명령은 CMP 혹은 유사 명령에 의해 설정된 동일한 플래그 값을 사용합니다.
고수준 코드와 CPU 분기의 매핑
다음과 같은 C 스타일 조건문을 생각해 보세요.
int valueA = 2;
int valueB = 3;
if (valueA == valueB) {
// do stuff
}
머신 레벨에서는 컴파일러가 일반적으로 다음과 같이 생성합니다.
CMP valueA, valueB–valueA - valueB에 기반해 플래그를 설정.JZ label– 제로 플래그가 설정되어 있으면(즉, 값이 동일하면) 해당 블록으로 점프.
따라서 복잡한 고수준 구조조차도 플래그를 설정하는 비교와 분기 명령의 연속으로 환원됩니다.