[CSAPP 3장 완전 정복] 3.6 – 조건문, 반복문, 분기 흐름을 어셈블리로 해석해보자

2025. 4. 8. 18:51·크래프톤 정글/컴퓨터구조(CSAPP)

조건문, 반복문, 분기 흐름을 어셈블리로 해석해보자

이번 절에서는 우리가 C에서 자주 사용하는 흐름 제어문들 (if, while, for, switch)이 어셈블리어에서는 어떤 방식으로 분기(Branch)와 조건 코드(Condition Code)를 통해 표현되는지를 매핑 중심으로 정리합니다.

 

 

흐름 제어의 핵심, ‘조건 코드’와 ‘분기 명령어’

C 코드에서 if (x > y) 같은 조건문은 어셈블리어에서 다음 두 단계로 해석됩니다.

  1. cmp 혹은 test 명령어로 조건 코드(플래그) 설정
  2. jX 형태의 조건 분기 명령어로 분기 결정

 

조건 코드란?

cmp a, b → 내부적으로 b - a를 계산하고 그 결과에 따라 다음 플래그를 설정합니다.

조건 코드 의미
ZF (Zero Flag) 결과가 0이면 1
SF (Sign Flag) 결과가 음수면 1
OF (Overflow Flag) 오버플로우 발생 시 1. (signed 분기에 사용)
CF (Carry Flag) 자리 올림/내림 발생 시 1. (unsigned 분기에 사용)

비교 자체는 결과를 저장하지 않고, 조건 플래그만 설정합니다.

 

 

조건 분기 명령어 종류

명령어 조건 의미
je(jz) / jne(jnz) ZF == 1 / 0 같음 / 다름
jg / jge SF==OF and ZF==0 / SF==OF 부호 있는 > / ≥
jl / jle SF≠OF / SF≠OF or ZF==1 부호 있는 < / ≤
ja / jae CF==0 and ZF==0 / CF==0 부호 없는 > / ≥
jb / jbe CF==1 / CF==1 or ZF==1 부호 없는 < / ≤

같은 비교 연산이라도 signed인지 unsigned인지에 따라 사용하는 분기 명령어가 다른데요. 대부분의 정수 연산은 기본적으로 signed 기준이지만, 메모리 주소나 크기 비교(size_t, strlen, malloc 등)처럼 음수가 될 수 없는 값들은 unsigned 분기 명령어(ja, jb 등)를 사용해야 정확합니다.

 

또한 하드웨어 수준에서는 레지스터를 비트 패턴 그 자체로 해석해야 하는 경우가 많기 때문에, 연산자 및 명령어의 맥락에 따라 signed/unsigned 판단이 달라질 수 있습니다.

 

 

분기 없는 조건 처리: cmov, setcc

cmov와 setcc는 조건에 따라 값을 이동하거나 설정하는 명령어로, 분기 없이 조건 처리를 할 수 있어 성능 최적화에 유리합니다.

cmovXX

cmp %rsi, %rdi
cmovg %rsi, %rax   ; 조건(rdi > rsi)이 참이면 rax = rsi
  • 조건이 참일 때만 값을 이동
  • 분기를 피할 수 있어 pipeline 효율이 좋음

setXX

cmp %rsi, %rdi
setl %al           ; 조건(rdi < rsi)이 참이면 al = 1, 아니면 0
  • 조건 결과를 1바이트 레지스터에 저장
  • Boolean 값을 만들 때 유용 (ex. 비교 결과 → 0 또는 1)

 

if-else, if-else if-else 문 구조 매핑

if-else 문 구조 매핑

if (x > y) {
  z = 1;
} else {
  z = 2;
}

위의 C 코드 if문을 어셈블리로 바꾸면 아래와 같습니다.

cmpq %rsi, %rdi          ; rdi - rsi → 조건 코드 설정 (rdi > rsi 인지 판단)
jle .Lelse               ; rdi <= rsi 이면 .Lelse로 분기 (rdi > rsi가 아니면 else 실행)

movl $1, z               ; 참일 경우: z = 1
jmp .Lend                ; 조건문 이후 공통 흐름으로 점프

.Lelse:
movl $2, z               ; 거짓일 경우: z = 2

.Lend:                   ; 조건문 끝 (공통 지점)

조건이 false일 때 jump, true일 경우 아래로 흐르는 구조입니다.

 

if-else if-else 문 구조 매핑

if (x == 0) {
  a = 1;
} else if (x == 1) {
  a = 2;
} else {
  a = 3;
}

어셈블리에서는 각 조건마다 cmp와 je/jne같은 분기 명령어를 쓰고, 중간에 jmp를 통해 전체 흐름을 제어합니다:

cmpl $0, %edi           ; edi와 0을 비교 (edi - 0 → 조건 코드 설정)
jne .Lelse1             ; edi != 0 이면 .Lelse1으로 분기 → 첫 번째 조건 실패

movl $1, a              ; edi == 0 → a = 1
jmp .Lend               ; 조건 만족했으니 나머지 생략하고 끝으로 이동

.Lelse1:
cmpl $1, %edi           ; edi와 1을 비교
jne .Lelse2             ; edi != 1 이면 .Lelse2으로 분기 → 두 번째 조건 실패

movl $2, a              ; edi == 1 → a = 2
jmp .Lend               ; 조건 만족했으니 끝으로 이동

.Lelse2:
movl $3, a              ; 위 조건들 모두 실패 → 기본값 a = 3

.Lend:                  ; 공통 종료 지점

C에서는 간단히 보이는 else if도 어셈블리어에서는 결국 연속된 조건 검사 + 다중 분기로 구현됩니다. 조건이 거짓일 때만 다음 비교로 넘어가며, 조건이 참이면 결과 수행 후 곧바로 루프에서 빠져나가는 구조입니다.

 

 

while, for, do-while 문 구조 매핑

while 문 구조 매핑

while (i < n) {
  sum += i;
  i++;
}

위의 C 코드 while문을 어셈블리로 바꾸면 아래와 같습니다.

.Ltest:
cmpq %rdx, %rsi         ; rsi < rdx 인지 검사 → 내부적으로 rsi - rdx → 조건 코드 설정
jge .Lend               ; rsi >= rdx 이면 종료 지점으로 분기 (조건 실패)

addq %rsi, %rax         ; rax += rsi (누적 덧셈)
incq %rsi               ; rsi += 1 (다음 반복을 위한 인덱스 증가)
jmp .Ltest              ; 조건 검사 위치로 점프 (루프 반복)

.Lend:                  ; 루프 종료 지점

 

for 문 구조 매핑

for (int i = 0; i < n; i++) {
  sum += i;
}

일반적인 for루프는 초기화 → 조건 검사 → 본문 → 증가 연산 순서로 동작합니다. 어셈블리에서는 다음과 같은 구조로 표현됩니다:

movl $0, %esi           ; 루프 인덱스 초기화: esi = 0
jmp .Ltest              ; 조건 검사 위치로 점프 (루프 진입 전)

.Lbody:
addl %esi, %eax         ; eax += esi (누적합 계산)
incl %esi               ; esi += 1 (인덱스 증가)

.Ltest:
cmpl %edx, %esi         ; esi < edx 인지 검사 → 내부적으로 esi - edx
jl .Lbody               ; 조건 만족하면 .Lbody로 점프 (루프 계속)
                        ; 조건 실패하면 루프 종료

while 루프와 구조는 거의 동일하지만, 초기화가 루프 밖에서 한 번만 수행되고, 증가 연산이 본문 뒤에 위치한다는 차이가 있습니다.

 

do-while 문 구조 매핑

do {
  sum += i;
  i++;
} while (i < n);

이어서 위의 C 코드 do-while문을 어셈블리로 바꾸면 아래와 같습니다.

.Lbody:
addq %rsi, %rax         ; rax += rsi (누적합 계산)
incq %rsi               ; rsi += 1 (인덱스 증가)
cmpq %rdx, %rsi         ; rsi < rdx 인지 검사 (rsi - rdx → 조건 코드 설정)
jl .Lbody               ; rsi < rdx 이면 다시 루프 반복
                        ; 조건 실패 시 루프 종료

while과 do-while의 차이는 조건 검사 위치입니다.

 

 

switch 문 매핑

switch (x) {
  case 0: a = 1; break;
  case 1: a = 2; break;
  default: a = 3;
}

마지막으로 위의 C 코드 switch문을 어셈블리로 바꾸면 다음과 같습니다.

cmp     $1, %edi          ; x > 1 인지 확인
ja      .Ldefault         ; → x > 1이라면 default로 이동

jmp     *.LJumptable(,%rdi,8)  ; jump table로 분기

.LJumptable:
.quad   .Lcase0
.quad   .Lcase1

.Lcase0:
    movl $1, a(%rip)
    jmp .Ldone

.Lcase1:
    movl $2, a(%rip)
    jmp .Ldone

.Ldefault:
    movl $3, a(%rip)

.Ldone:

컴파일러는 연속된 case들을 jump table로 최적화할 수 있습니다.

 

 

정리

C 흐름 제어 어셈블리 구조
if 조건 검사 + 조건 분기 (jX)
if-else 조건 분기 + 무조건 jump
while, for 조건 검사 → 본문 → jump
do-while 본문 → 조건 검사
switch jump table + 간접 jump
cmovXX, setXX 분기 없는 조건 처리 (데이터 이동/값 설정)

 

 

마치면서

C의 흐름 제어문은 어셈블리어에서 cmp/test로 조건 코드 설정 후, jXX 명령어로 흐름을 조절하는 구조로 구현됩니다. 그리고 signed와 unsigned 비교의 차이를 정확히 이해하면, 더 정밀하게 어셈블리를 해석할 수 있습니다.

 

다음은 구조체, 정렬, 패딩을 통해 메모리 배치의 정교함을 배우는 3.9절에 대해 다뤄보겠습니다. 감사합니다.

저작자표시 비영리 변경금지 (새창열림)

'크래프톤 정글 > 컴퓨터구조(CSAPP)' 카테고리의 다른 글

[CSAPP 3장 완전 정복] 3.10 기계 수준 프로그램에서 제어와 데이터는 어떻게 결합될까?  (0) 2025.04.09
[CSAPP 3장 완전 정복] 3.9 구조체는 메모리에서 어떻게 저장될까?  (0) 2025.04.08
[CSAPP 3장 완전 정복] 3.8.5 동적 배열(VLA), 주소 계산은 어떻게 달라질까?  (0) 2025.04.08
[CSAPP 3장 완전 정복] 3.8 배열, 포인터, 주소 계산의 모든 것  (0) 2025.04.07
[CSAPP 3장 완전 정복] 3.7 함수 호출, 스택, 레지스터의 삼각관계  (0) 2025.04.07
'크래프톤 정글/컴퓨터구조(CSAPP)' 카테고리의 다른 글
  • [CSAPP 3장 완전 정복] 3.10 기계 수준 프로그램에서 제어와 데이터는 어떻게 결합될까?
  • [CSAPP 3장 완전 정복] 3.9 구조체는 메모리에서 어떻게 저장될까?
  • [CSAPP 3장 완전 정복] 3.8.5 동적 배열(VLA), 주소 계산은 어떻게 달라질까?
  • [CSAPP 3장 완전 정복] 3.8 배열, 포인터, 주소 계산의 모든 것
그냥사람_
그냥사람_
IT 관련 포스팅을 합니다. 크래프톤 정글 8기 정경호
  • 그냥사람_
    그냥코딩
    그냥사람_
  • 전체
    오늘
    어제
    • 글 전체보기
      • 크래프톤 정글 N
        • 로드 투 정글(입학시험)
        • CS기초(키워드, 개념정리)
        • 컴퓨터구조(CSAPP)
        • Code 정글(C언어) N
        • 마이 정글(WIL, 에세이)
      • 자료구조&알고리즘
        • 자료구조
        • 알고리즘
      • 일상
  • 블로그 메뉴

    • 홈
  • 링크

    • Github
  • hELLO· Designed By정상우.v4.10.3
그냥사람_
[CSAPP 3장 완전 정복] 3.6 – 조건문, 반복문, 분기 흐름을 어셈블리로 해석해보자
상단으로

티스토리툴바