본문 바로가기
Computer Science/language

[assembly] x86 Assembly?

by yeong-yi 2025. 5. 24.
Contents
  • 해커의 언어: 어셈블리

컴퓨터 속에는 복잡한 논리적 인과관계가 존재하고, 여러 개체가 상호 작용하며, 통용되는 기계어라는 언어가 존재한다.

 

바이너리를 분석하는 리버스 엔지니어링은 동작 자체를 이해하는 작업을 수행해야 하기 때문에 컴퓨터의 언어(기계어)를 이해해야 한다.

시스템 해커가 가장 기본적으로 습득해야 하는 지식은 컴퓨터 언어에 관한 것. 컴퓨터의 언어로 작성된 소프트웨어에서 취약점을 발견해야 하기 때문이다. 하지만 기계어는 0과 1로만 구성돼 있어 우리가 이해하기 매우 어렵다.

 

  • 어셈블리 언어와 어셈블러

개발자들이 어셈블리어로 코드를 작성하면 어셈블러가 컴퓨터가 이해할 수 있는 기계어로 코드 치환

  • 역어셈블러

기계어로 구성된 소프트웨어를 역어셈블러에 넣으면, 어셈블리 코드로 번역

→ 소프트웨어를 분석하기 위해 기계어를 읽을 필요 x

  • 어셈블리어와 x86-64

어셈블리어는 컴퓨터의 기계어와 치환되는 언어

기계어가 여러 종류라면 어셈블리어도 여러 종류여야 함

CPU에 사용되는 ISA 종류에 따라 수 많은 어셈블리어 존재

어셈블리어 아키텍처별로 특정한 문법 구조를 지니며 각기 다름. x86-64 아키텍처Intel 문법 기준 학습

동사 역할의 명령어(Operation Code, Opcode)와 목적어 역할의 피연산자(Operand)로 구성

피연산자는 해당 연산의 입력 값(레지스터, 상수, 메모리 주소 등)이 되며 이때 피연산자의 개수는 0개 혹은 그 이상. 명령어에 따라 다름

mov eax, 3

 

명령어 예시

명령어 피연산자 개수
mov eax, 3 2
push rbp 1
add rax, 0x30 2

주요한 명령어

데이터 이동(Data Transfer) mov, lea
산술 연산(Arithmetic) inc, dec, add, sub
논리 연산(Logical) and, or, xor, not
비교(Comparison) cmp, test
분기(Branch) jmp, je, jg
스택(Stack) push, pop
프로시져(Procedure) call, ret, leave
시스템 콜(System call) syscall

피연산자

상수 / 레지스터 / 메모리

메모리 피연산자는 []로 표현되며 앞에 크기 지정자인 TYPEPTR이 올 수 있다.

TYPEPTR: BYTE(1byte), WORD(2byte=16bit), DWORD(3byte), QWORD(4byte)

크기 지정자를 통해 크기 명시하지 않으면 CPU입장에서 해당 메모리 주소에 몇 바이트를 가져와야 하는지 알 수 없기 때문에 오류 발생

mov [rdi], eax  ; (X) 오류 발생 가능: 몇 바이트를 가져올 것인지 크기 지정이 명확하지 않음
mov DWORD PTR [rdi], eax  ; (O) 명확한 크기 지정

 

메모리 피연산자의 예

WORD PTR [rax] rax가 가르키는 주소에서 데이터를 2바이트만큼 참조
QWORD PTR [0x8048000] 0x8048000의 데이터를 8바이트 만큼 참조