헤맨 만큼 내 땅이다
퀴즈 5번 : 어셈블리 → C 코드 복원 본문
cmpl / jle 조건부 분기를 읽다가 막혔던 지점들 정리
문제 상황
cmpl $0, %edi
jle .L1
movl $1, %edx
jmp .L2
.L1:
movl $0, %edx
.L2:
movl %edx, %eax
ret
int function(int x) {
int y;
if ( ____(1) )
_____(2);
else
y = 0;
return ____(3);
}
트러블 1 — %edi가 갑자기 왜 나오지? x는 어디 있는 거야?
증상: 코드 어디에도 x라는 글자가 없는데 갑자기 %edi가 등장해서 당황함.
원인: 함수 인자는 코드에 명시적으로 "담기는" 과정이 안 보여요. 함수가 시작되는 순간, 이미 첫 번째 인자가 %edi(4바이트 정수 인자 규칙)에 담긴 채로 시작하기 때문이에요.
해결: 어셈블리에서 %edi를 보면 자동으로 **"이건 x다"**라고 치환해서 읽는 습관을 들이기. 별도의 "대입" 코드가 있어야 하는 게 아니라, 함수 진입 시점부터 이미 그렇게 세팅되어 있다는 걸 전제로 깔고 읽어야 함.
트러블 2 — cmp가 뭔지 몰라서 첫 줄부터 막힘
증상: cmpl $0, %edi를 보고 "이게 뭘 하는 명령어인지" 전혀 감이 안 옴.
원인: cmp를 배운 적이 없거나, 배웠어도 "빼기랑 뭐가 다른지"가 명확하지 않았음.
해결 — 핵심 비유: 저울에 물건 두 개를 올려서 "몇 그램 차이 나는지"는 필요 없고 "어느 쪽이 무거운지"만 알고 싶은 상황과 같음.
cmpl $0, %edi
↓
x - 0을 계산은 하되, 그 결과값은 버림
대신 "결과가 양수/음수/0이었는지"만 CPU의 플래그(표시등)에 기록
왜 sub(진짜 빼기)를 안 쓰는지: sub를 쓰면 계산 결과가 레지스터에 그대로 덮어써져서, x의 원래 값을 잃어버림. cmp는 "비교만 하고 원본은 보존"하기 위한 전용 명령어.
트러블 3 — jle가 정확히 뭘 비교하는 건지 모르겠음
증상: jle .L1이 "무엇을" "무엇과" 비교해서 점프하는 건지 연결이 안 됨.
원인: jle는 그 자체로는 아무것도 비교하지 않음 — 바로 앞줄 cmp가 세팅해놓은 플래그를 읽기만 하는 명령어라는 연결고리를 놓침.
해결:
jle = jump if less or equal (작거나 같으면 점프)
바로 앞 cmp에서 계산한 게 "x - 0" 이었으므로:
jle의 조건 = "x - 0 ≤ 0" = "x ≤ 0"
정리: cmp가 "재료(플래그)"를 만들고, 바로 다음에 오는 조건부 점프가 그 재료를 "소비"한다는 2단계 구조로 항상 짝지어 읽기.
트러블 4 (가장 헷갈렸던 지점) — 왜 x ≤ 0이 아니라 x > 0으로 뒤집혀서 나오는가
증상: 분명 jle의 점프 조건은 x ≤ 0인데, 정답 C 코드에는 **if (x > 0)**이라고 반대로 적혀있음. "그냥 조건 그대로 쓰면 안 되나?"
원인 — 질문 자체가 다르다는 걸 놓침:
- 점프 조건이 답하는 질문 = "언제 else로 도망갈까?"
- if 조건이 답하는 질문 = "언제 then을 실행할까?"
이 둘은 같은 게 아니라 서로 반대되는 상황을 가리킴.
코드 구조로 확인:
cmpl $0, %edi
jle .L1 ← "조건 맞으면(x≤0) else로 도망가라"
movl $1, %edx ← 도망 안 갔을 때만 실행 = then 절 (y=1)
jmp .L2
.L1:
movl $0, %edx ← 도망가서 도착 = else 절 (y=0)
해결 — 뒤집기 공식:
점프 조건(jle): x ≤ 0 → 이건 "else로 가는 조건"
↓ 반대로 뒤집기
then 조건: x > 0 → 이게 실제 if문에 들어가는 조건
비유: "비가 오면 우산을 챙겨라"는 규칙만 있을 때, "우산을 안 챙기는 상황"이 궁금하면 그 규칙을 뒤집어야(=비가 안 오면) 답이 나오는 것과 같은 원리.
최종 정답
int function(int x) {
int y;
if (x > 0) // (1)
y = 1; // (2)
else
y = 0;
return y; // (3)
}
재발 방지 체크리스트 — 다음에 비슷한 문제 만나면
- 인자 → 레지스터 매핑부터 확인: %edi, %esi 등이 어떤 C 변수에 대응하는지 먼저 표시해두기
- cmp 줄 발견 시: "오퍼랜드2 - 오퍼랜드1"이 뭔지부터 적어보기 (여기선 x - 0)
- 조건부 점프(jle, je, jg...) 발견 시: 그 점프가 "어디로, 무슨 조건으로" 가는지 적기
- ★ 가장 중요: 조건부 점프는 대부분 **"else로 가는 티켓"**이지 "then으로 가는 티켓"이 아니므로, if문 조건을 쓸 땐 점프 조건을 반드시 반대로 뒤집는다
'week5' 카테고리의 다른 글
| 트러블슈팅2 (0) | 2026.09.30 |
|---|---|
| 02 Stack Buffer Overflow (off-by-one) (0) | 2026.09.22 |