hhkb.dev

BLOG

2025-10-06 / 어셈블리 · 01

어셈블리 개발 환경과 빌드 프로세스

어셈블리어를 시작할 때는 문법보다 먼저 실행 환경을 갖추는 게 중요하다. 여기서는 Ubuntu 기준으로 x86-64 어셈블리 개발 툴체인을 준비하고, Hello World를 빌드하는 기본 흐름을 정리한다.

1. 리눅스 환경의 필요성

리눅스 환경은 시스템 콜 호출 규약이 비교적 직관적이고, GDB 같은 디버깅 도구도 기본적으로 쓰기 좋다. 보안 분석 실무에서도 리눅스 바이너리 비중이 높아서, 처음 배우는 환경으로 무난하다.

실제로는 WSL2로 Ubuntu를 올려서 시작해도 충분하다.

2. 필수 도구 설치

빌드와 디버깅을 위해서는 아래 세 가지가 기본이다.

  • NASM(Netwide Assembler): .asm 소스를 오브젝트 파일로 바꾸는 어셈블러
  • GCC(GNU Compiler Collection): 링킹 과정을 간편하게 처리할 때 쓴다
  • GDB(GNU Debugger): 레지스터와 메모리 상태를 확인하는 디버거다
sudo apt update
sudo apt install nasm gcc gdb -y

3. Hello World 작성

여기서는 printf 같은 C 라이브러리 없이, 시스템 콜을 직접 호출해 문자열을 출력한다.

hello.asm

section .data
    msg db "Hello, Assembly!", 0x0a  ; 출력할 문자열 (\n 포함)

section .text
    global _start                    ; 진입점(Entry Point)

_start:
    ; 1. write(1, msg, 17)
    mov rax, 1                       ; sys_write
    mov rdi, 1                       ; stdout
    mov rsi, msg                     ; 버퍼 주소
    mov rdx, 17                      ; 길이
    syscall                          ; 커널 호출

    ; 2. exit(0)
    mov rax, 60                      ; sys_exit
    mov rdi, 0                       ; 종료 코드
    syscall

4. 빌드 및 실행

실행 파일을 만드는 과정은 어셈블과 링킹 두 단계로 나뉜다.

  1. 어셈블: 소스를 오브젝트 파일로 바꾼다.

    nasm -f elf64 hello.asm -o hello.o
    

    -f elf64로 64비트 ELF 포맷을 지정한다.

  2. 링킹: 실행 파일을 만든다.

    ld hello.o -o hello
    

    실무에서는 보통 이 과정을 매번 수동으로 치지 않고, Makefile이나 CMake 같은 도구로 묶어 관리한다.

  3. 실행:

    ./hello
    

이 과정을 한 번 직접 해보면, 고수준 언어가 감추고 있는 로우 레벨 동작이 어떻게 이어지는지 감이 잡힌다.