컴퓨터 프로그램은 단순히 순차적으로 명령어를 실행하는 것이 아닙니다.
우리가 if, for, while 같은 제어문으로 “만약 ~라면”, “반복하라”, “갈림길에서 어느 쪽으로 갈지”를 표현하듯이,
실제 기계어(어셈블리어)에서는 이러한 제어 구조를 비교 명령어, 조건부 점프, 무조건 점프와 함께
작은 플래그(조건 코드)를 이용해 제어합니다.
먼저, 조건문이나 반복문을 제대로 이해하려면 '조건 플래그'가 무엇인지 알아야 합니다.
조건 플래그는 계산 결과에 대해 “이 값이 0인가?”, “음수인가?”, “넘쳤나?”와 같은 정보를
1비트짜리 스위치처럼 저장해 놓은 것으로, 이후에 조건부 점프 명령어가 이 플래그들을 참고하여
프로그램의 흐름을 결정하게 됩니다.
1. 조건 플래그(Condition Codes) - 결과를 판단하는 작은 스위치
컴퓨터는 산술 및 논리 연산의 결과를 판단하기 위해 조건 플래그를 사용합니다. 계산 후, 결과가 "0인지", "음수인지", "오버플로우가 발생했는지" 등을 나타내기 위해 1비트 스위치들(플래그)을 설정합니다.
플래그 | 의미 | 설명 |
CF | Carry Flag (캐리 플래그) |
unsigned 덧셈에서 자리 올림이 발생하면 1로 설정됩니다. e.g. 결과가 원래보다 작으면 넘침 |
ZF | Zero Flag (제로 플래그) |
연산 결과가 0이면 1로 설정됩니다. |
SF | Sign Flag (사인 플래그) |
결과의 최상위 비트가 1이면 1로 설정됩니다. (즉, 결과가 음수임을 나타냄) |
OF | Overflow Flag (오버 플로우 플래그) |
signed 연산에서 표현 가능한 범위를 초과하면 1로 설정됩니다. e.g. 양수 두 개의 합이 음수로 표현될 때 |
e.g.
a와 b를 더해서 t를 만든다고 가정해 봅시다.
- 만약 t가 a보다 작다면, CF가 1로 설정되어 "오버플로우 발생"을 의미합니다.
- t가 0이면 ZF가 1,
- t가 음수이면 SF가 1,
- 만약 a와 b가 둘 다 양수(또는 음수)인데 t가 음수이면 OF가 1로 설정됩니다.
이 플래그들은 이후 조건부 점프 명령어에서 "조건이 참이면 이 레이블로 점프"하는 결정에 활용됩니다.
2. 어셈블리어 명령어와 C 제어문의 대응
주요 명령어 정리
명령어 | 의미 | 예시 |
cmp | 두 값을 비교하여 조건 플래그(Zero, Sign 등)를 설정 | cmp %rbx, %rax (즉, %rax와 %rbx를 비교) |
test | 비트 단위 AND 후 결과에 따라 플래그를 설정 | test %rax, %rax (값이 0인지 확인) |
je / jz | Zero Flag가 1이면(비교 결과 같으면) 지정된 레이블로 점프 | je label_equal |
jne / jnz | Zero Flag가 0이면(비교 결과 다르면) 지정된 레이블로 점프 | jne label_diff |
ji / jng | 부호 있는 비교에서 Less Than일 때 점프 | ji loop_start |
jmp | 무조건 지정한 레이블로 점프 | jmp loop_strat |
3. 조건문 - "만약 ~ 라면"을 C와 어셈블리어로 구현하기
e.g. in C
if (a == b) {
// 조건이 참일 때 실행할 코드
} else {
// 조건이 거짓일 때 실행할 코드
}
e.g. in Assembly
cmp %rbx, %rax ; %rax와 %rbx를 비교, 결과에 따라 플래그 설정 (예: ZF 설정)
je label_equal ; Zero Flag가 1이면(즉, a와 b가 같으면) label_equal로 점프
; 조건이 거짓일 때 실행할 코드
jmp end_condition
label_equal:
; 조건이 참일 때 실행할 코드
...
end_condition:
해설:
- cmp 명령어가 두 값을 비교하고, 그 결과에 따라 조건 플래그(e.g. ZF, SF, OF 등)를 설정합니다.
- je(jump if equal) 명령어는 ZF가 1인 경우에 지정된 레이블로 점프합니다.
- 이렇게 어셈블리어에서는 조건 코드와 조건부 점프를 통해 if문을 구현합니다.
4. 반복문 - "같은 작업을 계속 반복"하는 구조
e.g. in C
for (int i = 0; i < n; i++) {
// 반복 작업 수행
}
e.g. in Assembly
movl $0, %ecx ; 인덱스 i를 0으로 초기화
movl $n, %edx ; 반복 횟수 n을 %edx에 저장
loop_start:
; 여기서 반복 작업 수행 (예: 배열 요소 처리)
incl %ecx ; i 값을 1 증가
cmpl %edx, %ecx ; i와 n을 비교
jl loop_start ; i < n이면 loop_start로 점프
해설:
- 인덱스를 초기화하고, 각 반복 후 증가시키며 비교(cmp)를 통해 조건을 확인합니다.
- 조건이 참이면 jl (jump if less) 명령어로 다시 루프의 시작 부분으로 돌아갑니다.
5. 조건문과 반복문의 결합 - 배열에서 특정 값 찾기
e.g. in C
int array[n];
int target = 5;
for (int i = 0; i < n; i++) {
if (array[i] == target) {
// target을 찾으면 반복 종료
break;
}
}
e.g. in Assembly
movl $0, %ecx ; 인덱스 i = 0
movq array(%rip), %rsi ; 배열의 시작 주소를 %rsi에 저장
movl $n, %edx ; 배열의 크기 n
movl $target, %ebx ; 찾고자 하는 값을 %ebx에 저장
loop_search:
movl (%rsi, %rcx, 4), %eax ; 배열의 i번째 요소를 %eax에 로드
cmp %ebx, %eax ; %eax와 target을 비교 (cmp 명령어가 플래그 설정)
je found ; 같으면, 조건 플래그가 설정되어 found 레이블로 점프
incl %ecx ; 인덱스 i를 1 증가
cmpl %edx, %ecx ; i와 n을 비교
jl loop_search ; 조건이 만족되면 반복
jmp end_search ; target을 찾지 못한 경우
found:
; target을 찾았을 때 실행할 코드
...
end_search:
6. 마무리
이번 글에서는 CSAPP 3.6장의 조건문, 반복문, 분기문이 C언어와 어셈블리어에서 어떻게 구현되는지를 살펴보았습니다.
- 조건 플래그(CF, ZF, SF, OF)는 계산 결과를 판단하는 작은 불빛(1비트 스위치)처럼 작동하며, 조건부 점프 명령어가 이 플래그들을 참조하여 프로그램의 흐름을 결정합니다.
- 조건문은 cmp와 조건부 점프를 통해 if문을 구현하며,
- 반복문은 인덱스 초기화, 비교, 조건부 점프를 통해 for/while문의 기능을 수행합니다.
- 마지막으로, 조건문과 반복문을 결합하면 배열 탐색과 같은 실제 문제 해결에 적용할 수 있습니다.
'CSAPP > 3장' 카테고리의 다른 글
[CSAPP] 3-8 배열의 할당과 접근 (0) | 2025.04.15 |
---|---|
[CSAPP] 3-7 프로시저 (0) | 2025.04.09 |
[CSAPP] 3-5 산술연산과 논리연산 (0) | 2025.04.08 |
[CSAPP] 3-4 정보 접근하기 (0) | 2025.04.08 |
[CSAPP] 3-3 데이터 형식 (0) | 2025.04.08 |