x86-64 assembly
어셈블리 언어
2 분 소요
어셈블리 언어
기본 구조
- 명령어 opcode
- 피연산자 operand
- mov eax, 3 -> mov(명령어) eax(operand1) 3(operand2)
명령코드 |
|
데이터 이동 |
mov, lea |
산술 연산 |
inc, dec, add, sub |
논리 연산 |
and, or, xor, not |
비교 |
cmp, test |
분기 |
jmp, je, jg |
스택 |
push, pop |
프로시저 |
call, ret, leave |
시스템 콜 |
syscall |
피연산자
- 피연산자에는 3가지 종류가 올 수 있음
- 메모리 피연산자는 []으로 둘러싸인 것으로 표현되며, 앞에 TYPE PTR이 추가될 수 있음
- 타입의 종류
- BYTE, WORD, DWORD, QWORD
- 1바이트, 2바이트, 4바이트, 8바이트
- QWORD PTR [0x804800] -> 0x804800의 데이터를 8바이트만큼 참조
어셈블리 명령어
- mov dst, src => src에 들어있는 값을 dst에 대입
- lea dst, src => src의 유효 주소(Effective Address, EA)를 dst에 저장
- add dst, src => dst에 src의 값을 더함
- sub dst, src => dst에서 src의 값을 뺌
- inc op => op의 값을 1 증가시킴
- dec op => op의 값을 1 감소시킴
- 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 op1,op2 => op1과 op2를 비교 (플래그 레지스터 보고 판단 가능)
- test op1,op2 => 두 피연산자에 and 연산을 취함
- jmp addr => addr로 rip를 이동시킴
- je addr => 직전에 비교한 두 피연산자가 같으면 점프 (jump if equal)
- jg addr => 직전에 비교한 두 연산자 중 전자가 더 크면 점프 (jump if greater)
스택
- push val => val을 스택 최상단에 쌓음
- pop reg => 스택 최상단에서 값을 꺼내서 reg에 대입
프로시저
- 컴퓨터 과학에서 프로시저(Procedure)는 특정 기능을 수행하는 코드 조각을 말함
- 프로시저를 사용하면 반복되는 연산을 프로시저 호출로 대체할 수 있어 전체 코드의 크기를 줄일 수 있음
- 기능별로 코드 조각에 이름을 붙일 수 있게 되어 코드의 가독성을 크게 높일 수 있음
- 프로시저를 부르는 행위를 호출(Call)이라고 하며, 프로시저에서 돌아오는 것을 반환(Return)이라고 부름
- 프로시저를 호출할 때는 프로시저를 실행하고 나서 원래의 실행 흐름으로 돌아와야 하기 때문에 call 다음의 명령어 주소를 스택에 저장하고 프로시저로 rip를 옮김
- x64 어셈블리언어에는 프로시저의 호출과 반환을 위한 call, leave, ret 명령어가 존재
- call addr => addr에 위치한 프로시저 호출
- push return_address
- jmp addr
- 함수를 호출할 때 돌아와야 하기 때문에 스택에 반환 주소를 넣고 함수의 주소로 jmp 해야 함
- leave => 스택프레임 정리
- ret => return address로 반환
시스템 콜
- 운영체제는 커널 모드와 유저 모드가 존재
- 커널 모드는 파일시스템, 입력/출력, 네트워크 통신, 메모리 관리 등 저수준 작업
- 유저 모드는 유튜브 시청, 프로그래밍 등
- 시스템 콜은 유저 모드에서 커널 모드로의 권한이 필요할 때 사용됨 예) cat flag
- x64 아키텍처는 시스템 콜을 위해 syscall 명령어가 있음
- 요청: rax
- 인자 순서: rdi -> rsi -> rdx -> rcx -> r8 -> r9 -> stack
- 아래 rax를 통해 어떤 요청인지 알 수 있고, rdi rsi rdx를 통해 출력 스트림, 출력 버퍼, 출력 길이 등을 알 수 있음

댓글남기기