x86 어셈블리
: 기본적인 x86-64 어셈블리어에 대한 이해
rsp -= 8
[rsp] = val
rsp += 8
reg = [rsp-8]
프로시저(Procedure) : 특정 기능을 수행하는 코드 조각
-> 반복되는 연산을 프로시저 호출로 대체 가능, 전체 코드의 크기를 줄임
-> 기능별로 코드 조각에 이름을 붙일 수 있게 되어 코드의 가독성을 크게 높일 수 있음
호출(Call) : 프로시저를 부르는 행위
반환(Return) : 프로시저에서 돌아오는 것
push return_address
jmp addr
mov rsp, rbp
pop rbp
스택 프레임 : 함수별로 자신의 지역변수 또는 연산과정에서 부가적으로 생겨나는 임시 값들을 저장하는 영역, 함수별로 사용하는 영역을 구분하기 위해 스택프레임이 사용됨
pop rip
- func 함수 호출 후 다음 명령의 주소는 스택에 push 됨
- 기존의 스택 프레임을 저장하기 위해 기존의 rbp를 스택에 push
- 새로운 스택 프레임을 만들기 위해 rbp를 rsp로 이동
- 새로운 스택 프레임의 공간을 확장하기 위해 rsp를 몇 정도 뺌
- 할당한 스택 프레임에서 지역 변수 할당, 여러 연산 수행
- 저장해뒀던 기존의 rbp를 꺼내 rbp에 대입 (leave 연산) → 원래의 스택 프레임으로 복귀
- 저장해뒀던 반환 주소를 꺼내서 (ret 연산) 원래의 실행 흐름으로 복귀
시스템 콜 (system call, syscall) 은 유저 모드에서 커널 모드의 시스템 소프트웨어에게 어떠한 동작을 하기 위한 도움 요청
필요한 기능과 인자에 대한 정보를 레지스터로 전달하면, 커널이 이를 읽어서 요청을 처리
요청: rax
인자 순서: rdi → rsi → rdx → rcx → r8 → r9 → stack
syscall rax rdi rsi rdx read 0x00 unsigned int fd char *buf size_t count write 0x01 unsigned int fd const char *buf size_t count open 0x02 const char *filename int flags umode_t mode close 0x03 unsigned int fd mprotect 0x0a unsigned long start size_t len unsigned long prot connect 0x2a int sockfd struct sockaddrn * addr int addrlen execve 0x3a const char *filename const char const argv const char const envp rdi - 파일 디스크립터
rsi - 문자형 포인터 (주소)
rdx - 바이트 사이즈