드림핵
x86 Assembly
다다x_x
2025. 3. 10. 09:27
명령어(Operation Code, Opcode)와 피연산자(Operand)로 구성
명령어
데이터 이동(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
|
피연산자
- 상수(Immediate Value)
- 레지스터(Register)
- 메모리(Memory)
- [메모리주소]
- 앞에 크기 지정자(Size Directive) TYPE PTR이 추가 가능
- 타입에는 BYTE, WORD, DWORD, QWORD
각각 1바이트, 2바이트, 4바이트, 8바이트
데이터 이동 - mov, lea
- 어떤 값을 레지스터나 메모리에 옮기도록 지시
- mov dst, src
- src에 들어있는 값을 dst에 대입 (dst가 주소면 주소에 대입)
- lea dst, src
- src의 주소(Effective Address, EA)를 dst에 저장
산술 연산 - add, sub, inc, dec
- add dst, src
- dst + src
- sub dst, src
- dst - src
- inc op
- op + 1
- dec op
- op - 1
논리 연산 - and, or, xor, not
비트 연산
- and dst, src
- dst와 src의 비트가 모두 1이면 1, 아니면 0
- or dst, src
- dst와 src의 비트 중 하나라도 1이면 1, 아니면 0
- xor dst, src
- dst와 src의 비트가 서로 다르면 1, 같으면 0
- not op
- op의 비트 전부 반전
비교 - cmp, test
두 피연산자의 값을 비교하고, 플래그 설정
- cmp op1, op2
- 두 피연산자를 빼서 대소를 비교
- test op1, op2
- 두 피연산자에 AND 비트연산
분기 - jmp, je, jg
rip를 이동, 실행 흐름 변화
- jmp addr
- addr로 rip를 이동
- je addr
- 직전에 비교한 두 피연산자가 같으면 점프 (jump if equal)
- jg addr
- 직전에 비교한 두 연산자 중 전자가 더 크면 점프 (jump if greater)
스택 - push, pop
- push val
- val을 스택 최상단에 쌓음
- rsp -= 8
[rsp] = val
- pop reg
- 스택 최상단의 값 꺼내서 reg에 대입
- rsp += 8
reg = [rsp-8]
프로시저 - call, leave, ret
프로시저(Procedure) : 특정 기능을 수행하는 코드 조각
→ 반복되는 연산을 프로시저 호출로 대체
호출(Call)
→
반환(Return)
call 다음의 명령어 주소(Return Address, 반환 주소)를 스택에 저장하고 프로시저로 rip를 이동
- call addr
- addr에 위치한 프로시져 호출
- push return_address
jmp addr
- leave
- 스택프레임 정리
- mov rsp, rbp
pop rbp
- ret
- return address로 반환
- pop rip
시스템 콜 - syscall
- 커널 모드 : 운영체제가 전체 시스템을 제어하기 위해 시스템 소프트웨어에 부여하는 권한
커널 모드에서는 시스템의 모든 부분을 제어 - 유저 모드 : 운영체제가 사용자에게 부여하는 권한
- 시스템 콜(system call, syscall) : 유저 모드에서 커널에게 어떤 동작을 요청
- syscall
- rax : 시스템 콜의 종류 (read, write 등)
- rdi , rsi , rdx : 인자들
참조
https://learn.dreamhack.io/567