← 목록으로

어셈블리어 읽기 기초 (x86-64)

[Rev] 리버싱 · 작성: 2026-07-19 19:32:50 · 조회 4

디컴파일러가 있어도 결국 중요한 분기나 이상하게 최적화된 부분은 어셈블리를 직접 읽어야 확실해진다. 이 글은 리버싱에서 실제로 가장 자주 마주치는 x86-64 명령어 패턴 위주로 정리한다 — 명령어 전체를 외우는 게 목표가 아니라, "이 패턴을 보면 뭘 하려는 코드인지" 감을 잡는 게 목표다.

문법: AT&T vs Intel

같은 명령어라도 두 가지 표기법이 있다. 리버싱 도구들은 대부분 Intel 문법을 기본으로 쓴다 (더 읽기 편해서).

AT&T:   mov %eax, %ebx        ; 방향: 왼쪽 → 오른쪽
Intel:  mov ebx, eax          ; 방향: 오른쪽 → 왼쪽 (목적지가 먼저 온다)

이 글은 Intel 문법 기준이다.

데이터 이동

mov eax, 5        ; eax에 5를 대입
mov eax, [rbp-8]  ; rbp-8 주소에 있는 값을 eax로 읽어옴 (지역 변수 읽기)
mov [rbp-8], eax  ; eax 값을 rbp-8 주소에 저장 (지역 변수 쓰기)
lea rax, [rbp-8]  ; rbp-8 이라는 "주소 자체"를 rax에 저장 (값이 아니라 포인터)

[rbp-8]처럼 대괄호가 있으면 "그 주소에 있는 값"을 가리킨다. lea(Load Effective Address)만 예외적으로 주소 계산 결과 자체를 저장한다.

비교와 분기 — 제일 많이 보게 되는 패턴

cmp eax, 0x1337
je  success        ; eax == 0x1337 이면 success로 점프

test eax, eax
jz  fail            ; eax == 0 이면 fail로 점프 (NULL/실패 코드 체크에 흔함)

cmp eax, ebx
jg  greater          ; eax > ebx (signed)
ja  above             ; eax > ebx (unsigned)

cmp A, BA - B를 계산해서 결과 플래그(Zero, Sign, Carry 등)만 세팅하고, 그 다음 조건부 점프(je/jne/jg/jl/ja/jb...)가 그 플래그를 보고 분기한다. "정답 체크" 로직은 거의 항상 이 cmp + 조건분기 조합이라서, crackme를 풀 때 제일 먼저 찾는 패턴이다.

test eax, eaxcmp eax, 0과 사실상 같은 효과를 내는 관용적인 표현이다.

함수 호출

mov edi, 5      ; 첫 번째 인자
mov esi, 10     ; 두 번째 인자
call add_numbers
; 리턴값은 eax(또는 rax)에 담겨서 돌아옴

x86-64 System V 호출 규약에서 처음 6개 정수형 인자는 RDI, RSI, RDX, RCX, R8, R9 순서로 들어간다. 함수 호출부만 봐도 몇 개의 인자를 넘기는지, 대략 뭘 하는 함수인지 유추할 수 있다.

반복문 패턴

xor ecx, ecx        ; ecx = 0 (카운터 초기화, 흔한 관용구)
loop_start:
    cmp ecx, 10
    jge loop_end      ; ecx >= 10 이면 종료
    ; ... 반복할 코드 ...
    inc ecx
    jmp loop_start
loop_end:

for/while 문이 컴파일되면 결국 "비교 + 조건 점프 + 뒤로 점프"의 조합으로 풀어진다. 디컴파일러는 이걸 다시 for문으로 재구성해서 보여주지만, 최적화가 심하면 이 재구성이 부정확할 수 있어서 원본 어셈블리로 검증하는 게 안전하다.

다음 단계

여기까지가 정적으로 코드를 읽는 데 필요한 최소한이다. 실제 실행 흐름(어떤 값이 어떻게 변하는지)을 확인하려면 동적 분석(디버거)이 필요하고, 다음 글에서 다룬다.

리버싱 카테고리의 글 (2/11)

  1. 리버싱이란 무엇인가: 정적 분석 기초
  2. 어셈블리어 읽기 기초 (x86-64)
  3. 동적 분석: 디버거로 실행 흐름 추적하기
  4. 안티 디버깅 / 안티 리버싱 기법과 우회
  5. 패킹과 언패킹: 실행 파일을 압축/암호화해서 숨기기
  6. Frida로 동적 계측/후킹하기
  7. 안드로이드 앱 리버싱: APK 분석 기초
  8. iOS 앱 리버싱 기초
  9. 크랙미(Crackme) 실습 방법론
  10. PE 포맷 내부 구조: Windows 실행 파일 뜯어보기
  11. 코드 난독화 해제: Control Flow Flattening 분석하기
← 리버싱이란 무엇인가: 정적 분석 기초 동적 분석: 디버거로 실행 흐름 추적하기 →