시스템 콜은 사용자와 커널 사이의 인터페이스를 위한 API이다. 우리는 이미 시스템 콜을 사용했다. 스크린에 출력하는 sys_write과 프로그램에서 탈출하는 sys_exit가 시스템 콜이다.
macOS의 시스템 콜 번호는 리눅스에서 사용하는 시스템 콜 번호와 다르다.(e.g. 'write'은 macOS에서는 '0x2000004'이지만 리눅스에서는 '1'이다.) 시스템 콜 번호는 오프셋 0x200000
를 추가해야 한다. macOS는 네 가지의 시스템 콜 클래스를 가지고 있기 때문이다. 시스템 콜 번호의 상위 비트는 시스템 콜의 클래스를 나타내며 write, exit의 경우는 SYSCALL_CLASS_UNIX이므로 상위 비트는 2이다. 그러므로 모든 Unix 시스템 콜은 (0x200000 + unix syscall #)이다.
프로그램에서 macOS 시스템 콜을 사용하는 방법은 아래와 같다.
❗️ 위의 방법은 64비트 macOS 환경에서 시스템 콜을 호출하는 방법이다.
exit 시스템 콜을 사용하는 코드
mov rax, 0x2000001 ; 시스템 콜 번호 (exit)
mov rdi, 0 ; exit 함수의 파라미터에 0을 저장한다.
; 그렇지 않으면 프로그램 종료 시 exit code를 리턴한다.
syscall ; 시스템 콜 호출
write 시스템 콜을 사용하는 코드
mov rdx, 4 ; 메세지 길이
mov rsi, msg ; 출력할 메세지
mov rdi, 1 ; 파일 디스크립터(표준출력)
mov rax, 0x2000004 ; 시스템 콜 번호 (write)
syscall ; 시스템 콜 호출
아래의 예제는 키보드로 숫자를 읽어서 스크린에 출력하는 코드이다.
❗️ 64비트 Intel macOS에서 동작하는 코드이다.
section .data
userMsg db 'Please enter a number: '
lenUserMsg equ $ - userMsg
dispMsg db 'You have entered: '
lenDispMsg equ $ - dispMsg
section .bss ; 초기화 되지 않은 데이터
num resb 5
section .text
global _main
_main:
mov rax, 0x2000004
mov rdi, 1
mov rsi, userMsg
mov rdx, lenUserMsg
syscall
mov rax, 0x2000003
mov rdi, 2
mov rsi, num
mov rdx, 5
syscall
mov rax, 0x2000004
mov rdi, 1
mov rsi, dispMsg
mov rdx, lenDispMsg
syscall
mov rax, 0x2000004
mov rdi, 1
mov rsi, num
mov rdx, 5
syscall
mov rax, 0x2000001
mov rdi, 0 ; exit 함수의 파라미터에 0을 저장한다.
; 그렇지 않으면 프로그램 종료 시 exit code를 리턴한다.
syscall
코드를 컴파일하고 실행하면 아래의 결과를 확인할 수 있다.
Please enter a number:
1234
You have entered:1234
tutorialspoint.com
Making system calls from Assembly in Mac OS X
Learning NASM on macOS