[ DreamHack ] x86 Assembly
어셈블러 - 개발자들이 어셈블리어로 코드를 작성하면 컴퓨터가 이해할 수 있는 기계어로 코드를 치환해줌
어셈블리어 - 컴퓨터의 기계어로 치환되는 언어, low-level programming language에 속함
x86-64 어셈블리 언어
피연산자
총 3가지 종류가 올 수 있다 -> 상수 / 레지스터 / 메모리
메모리 : [대괄호]로 둘러싸인 것으로 표현됨. 앞에 크기 지정자 TYPE PTR(BYTE, WORD, DWORD, QWORD)이 추가될 수 있다.
ex) QWORD PTR [0x8048000] = 0x8048000의 데이터를 8바이트만큼 참조함
데이터 이동 - 어떤 값을 레지스터나 메모리에 옮기도록 지시함
연산자 | 사용 예시 | 해석 |
mov | mov des, src | src에 들어있는 값을 dst에 대입 |
lea | lea dst, src | src의 유효 주소(EA : Effective Address)를 dst에 저장 |
산술 연산 - 사칙연산을 지시함
연산자 | 사용 예시 | 해석 |
add | add dst, src | dst에 src의 값을 더함 |
sub | sub dst, src | dst에서 src의 값을 뺌 |
inc | inc op | op의 값을 1 증가시킴 |
dec | dec op | op의 값을 1 감소시킴 |
논리 연산 - 비트 연산을 지시함
연산자 | 사용 예시 | 해석 |
and | and dst, src | dst와 src의 비트가 모두 1이면 1, 아니면 0을 반환 |
or | or dst, src | dst와 src의 비트 중 하나라도 1이면 1, 아니면 0 |
xor | xor dst, src | dst와 src의 비트가 서로 다르면 1, 같으면 0 |
not | not op | op의 비트를 전부 반전 |
비교 - 두 피연산자의 값을 비교하고, 플래그를 반환
연산자 | 사용 예시 | 해석 |
cmp | cmp op1, op2 | op1과 op2를 비교 (두 피연산자를 빼서 대소를 비교) |
test | test op1, op2 | op1과 op2를 비교 (두 피연산자에 AND 비트 연산을 취함) |
분기 - rip를 이동시켜 프로그램 실행의 흐름을 바꿈
연산자 | 사용 예시 | 해석 |
jmp | jmp addr | addr로 rip를 이동 |
je | je addr | 직전에 비교한 두 피연산자가 같으면 점프 (jump if equal) |
jg | jg addr | 직전에 비교한 두 연산자 중 전자가 더 크면 점프 (jump if greater) |
스택
연산자 | 사용 예시 | 해석 |
push | push val | rsp를 8만큼 빼고, val을 스택의 최상단에 쌓음 |
pop | pop reg | 스택 최상단의 값을 reg에 대입, rsp를 8만큼 더함 |
- 스택 : 함수별로 자신의 지역변수 or 연산과정에서 부차적으로 생겨나는 임시 값들을 저장하는 영역
프로시저(Procedure)
: 특정 기능을 수행하는 코드 조각을 말함, 반복되는 연산을 프로시저 호출로 대체하여 전체 코드의 크기를 줄일 수 있음
연산자 | 사용 예시 | 해석 |
call | call addr | addr에 위치한 프로시저 호출 |
leave | leave | 스택프레임 정리 |
ret | ret | return address로 반환 |
- 스택프레임 : 함수별로 서로가 사용하는 스택의 영역을 명확히 구분하기 위해 사용
스택 프레임의 할당과 해제 과정
시스템 콜(system call, syscall) - 유저 모드에서 커널 모드의 시스템 소프트웨게 어떠한 동작을 요청하기 위해 사용
- 필요한 기능과 인자에 대한 정보를 레지스터로 전달하면 커널이 이를 읽어 요청을 처리함
- in Linux : x64아키텍처에서 rax로 무슨 요청인지 나타내고, 순서대로 필요한 인자를 전달함
syscall 예시



syscall table을 보면, rax가 0x1일 때, 커널에 write 시스템콜을 요청함
rdi, rsi, rdx가 0x1, 0x401000, 0xb 이므로 커널은 write(0x1, 0x401000, 0xb)를 수행하게 됨
write함수의 각 인자는 출력 스트림, 출력 버퍼, 출력 길이를 나타내는데
여기서 0x1은 stdout이며, 이는 일반적으로 화면을 의미함
0x401000에는 Hello World가 저장되어 있고,
길이는 0xb로 지정되어 있으므로 화면에 Hello World가 출력