x86 assembly system call
[1. System call]
시스템 콜은 운영체제(커널) 이 제공하는 서비스이다.
예를 들어, C 언어에서 파일을 열고 데이터 작성 및 저장 시, 물리 디스크에 직접 저장하는 코드를 작성하지 않고,
운영체제가 제공하는 함수, 이 경우에서는 write() 같은 시스템 콜을 활용 할 수 있다.
[2. x86 system call]
assembly 로 작성한 코드도 어셈블러에 의해 컴파일(어셈블) 된 뒤
링커에 의해 링킹 후 실행파일이 되어 하나의 프로그램이 된다.
따라서 assembly 에서도 커널이 제공하는 시스템 콜을 사용 할 수 있다.
다만, 시스템 콜 호출을 위한 지켜야 할 규칙이 있다.
시스템 콜은 호출을 위한 시스템 콜 번호가 정해져 있다.
32bit 와 64bit 에서 시스템 콜 번호가 다르긴 하지만,
이러한 시스템 콜 번호를 특정 레지스터에 저장 및, 기타 매개변수들을 정해진 레지스터에 저장 한 후
인터럽트를 발생시키는 것이다.
그래서 시스템 콜을 보통 software interrupt 라고 부르기도 한다.
[3. System call table 및 interrupt]
앞서, 시스템 콜 번호는 32bit 와 64bit 에서 다르다고 하였다.
그래서 32bit 는 아래를 참조하고
Linux System Call Table (nps.edu)
64bit 는 아래를 참조하도록 한다.
Linux System Call Table for x86 64 · Ryan A. Chapman (rchapman.org)
또한, system call 호출을 위한 인터럽트 발생에서
legacy 한 방식은
int 0x80 이라는 assembly 코드를 작성하는 것이다.
하지만 이러한 방식보다는 아래와 같은 방법이 더 적합하다.
x86-32: sysenter
x86-64: syscall
참조: assembly - What is better "int 0x80" or "syscall" in 32-bit code on Linux? - Stack Overflow
[4. Example]
아래 예제는 x86-64 이며, intel syntax 로 작성하였다.
이후에도 intel syntax 로 작성한다.
동작은 rcx register 에 42 를 저장 후, exit(42) 를 호출하는 것이다.
$ vim exit.s
; exit(22)
section .text
global _start
_start:
xor rcx, rcx
dummy:
add rcx, 20
inc rcx
cmp rcx, 21
je dummy
mov rax, 60
mov rdi, rcx
syscall
$ nasm -f elf64 exit.s
$ ld -o exit.o exit
$ ./exit ; echo $?
42 를 확인 할 수 있다.