diff --git a/cat.s b/cat.s index 887375f..5c345e6 100644 --- a/cat.s +++ b/cat.s @@ -1,8 +1,13 @@ ;; -*- mode: nasm -*- -;; Select the one that matches your os -%include "linux.s" -;%include "freebsd.s" +%define SYS_open 0x2 +%define SYS_close 0x3 +%define SYS_write 0x1 +%define SYS_read 0x0 +%define SYS_lseek 0x8 +%define SYS_exit 0x3c +%define O_RDONLY 0x0 +%define SEEK_SET 0x0 %define FD_stderr 2 %define FD_stdout 1 %define FD_stdin 0 @@ -12,290 +17,290 @@ section .text global _start _start: - pop rax ; argc - pop QWORD [exec_name] ; argv[0] + pop rax ; argc + pop QWORD [exec_name] ; argv[0] check_arg_loop: - mov rdi,[rsp] ; argv[i] - ; check for null - cmp rdi,0 - je print_stdin_and_exit + mov rdi,[rsp] ; argv[i] + ; check for null + cmp rdi,0 + je print_stdin_and_exit - ; check for flags - call check_flag - cmp rax,0 - je print_files ; no more flags + ; check for flags + call check_flag + cmp rax,0 + je print_files ; no more flags - pop rdi ; remove argv[i] (a flag) - jmp check_arg_loop + pop rdi ; remove argv[i] (a flag) + jmp check_arg_loop print_files: - mov rdi,[rsp] ; argv[i] - cmp rdi,0 - je print_files_end + mov rdi,[rsp] ; argv[i] + cmp rdi,0 + je print_files_end - ; check if argv[i] is '-' - mov rsi,dash_str - call streql - cmp rax,0 - jne print_files_stdin + ; check if argv[i] is '-' + mov rsi,dash_str + call streql + cmp rax,0 + jne print_files_stdin - ; open file - mov rdi,[rsp] ; argv[i] - call open_file + ; open file + mov rdi,[rsp] ; argv[i] + call open_file - ; print file - mov rdi,rax - pop rsi ; argv[i] - call print_file + ; print file + mov rdi,rax + pop rsi ; argv[i] + call print_file - jmp print_files + jmp print_files print_files_stdin: - pop rdi ; argv[i] - mov rdi,FD_stdin - mov rsi,stdin_name - call print_file + pop rdi ; argv[i] + mov rdi,FD_stdin + mov rsi,stdin_name + call print_file - ; rewind stdin + ; rewind stdin mov rax,SYS_lseek - mov rdi,FD_stdin - mov rsi,0 - mov rdx,SEEK_SET - syscall + mov rdi,FD_stdin + mov rsi,0 + mov rdx,SEEK_SET + syscall - jmp print_files + jmp print_files print_files_end: - xor rdi,rdi - jmp exit + xor rdi,rdi + jmp exit -open_file: ; int open_file(const char *path) - push rdi ; path +open_file: ; int open_file(const char *path) + push rdi ; path - ; open file - mov rax,SYS_open - ; rdi already set - mov rsi,O_RDONLY - syscall + ; open file + mov rax,SYS_open + ; rdi already set + mov rsi,O_RDONLY + syscall - ; check return - cmp rax,0 - jl open_error + ; check return + cmp rax,0 + jl open_error - pop rdi ; path - ret + pop rdi ; path + ret open_error: - call start_error + call start_error - ; message - mov rax,SYS_write - mov rdi,FD_stderr - mov rsi,open_error_text - mov rdx,open_error_text_len - syscall + ; message + mov rax,SYS_write + mov rdi,FD_stderr + mov rsi,open_error_text + mov rdx,open_error_text_len + syscall - ; detail - mov rdi,[rsp] ; path - call strlen + ; detail + mov rdi,[rsp] ; path + call strlen - mov rdx,rax - mov rax,SYS_write - mov rdi,FD_stderr - pop rsi ; path - syscall + mov rdx,rax + mov rax,SYS_write + mov rdi,FD_stderr + pop rsi ; path + syscall - call end_error + call end_error - mov rdi,1 - jmp exit + mov rdi,1 + jmp exit print_stdin_and_exit: - mov rdi,FD_stdin - mov rsi,stdin_name - call print_file - xor rdi,rdi - jmp exit + mov rdi,FD_stdin + mov rsi,stdin_name + call print_file + xor rdi,rdi + jmp exit -print_file: ; void print_file(int fd, const char *name) - push rdi ; fd - push rsi ; name +print_file: ; void print_file(int fd, const char *name) + push rdi ; fd + push rsi ; name print_file_loop: - mov rax,SYS_read - mov rdi,[rsp + 8] ; fd - mov rsi,read_buff - mov rdx,BUFFER_SIZE - syscall + mov rax,SYS_read + mov rdi,[rsp + 8] ; fd + mov rsi,read_buff + mov rdx,BUFFER_SIZE + syscall - ; check error - cmp rax,0 - jl read_file_error + ; check error + cmp rax,0 + jl read_file_error - ; no more bytes - je print_file_end + ; no more bytes + je print_file_end - ; print message - mov rdx,rax - mov rax,SYS_write - mov rdi,FD_stdout - mov rsi,read_buff - syscall + ; print message + mov rdx,rax + mov rax,SYS_write + mov rdi,FD_stdout + mov rsi,read_buff + syscall - jmp print_file_loop + jmp print_file_loop print_file_end: - pop rsi ; name - pop rdi ; fd - ret + pop rsi ; name + pop rdi ; fd + ret read_file_error: - call start_error + call start_error - ; message - mov rax,SYS_write - mov rdi,FD_stderr - mov rsi,read_error_text - mov rdx,read_error_text_len - syscall + ; message + mov rax,SYS_write + mov rdi,FD_stderr + mov rsi,read_error_text + mov rdx,read_error_text_len + syscall - ; detail - mov rdi,[rsp] ; name - call strlen + ; detail + mov rdi,[rsp] ; name + call strlen - mov rdx,rax - mov rax,SYS_write - mov rdi,FD_stderr - pop rsi ; name - syscall + mov rdx,rax + mov rax,SYS_write + mov rdi,FD_stderr + pop rsi ; name + syscall - call end_error + call end_error - mov rdi,1 - jmp exit + mov rdi,1 + jmp exit ;; check arg for -u, exit if unknown flag ;; return 1 if found, 0 otherwise -check_flag: ; bool check_arg(const char *arg) - xor rax,rax - ; check if arg[0] == '-' - cmp BYTE [rdi],'-' - jne check_flag_end +check_flag: ; bool check_arg(const char *arg) + xor rax,rax + ; check if arg[0] == '-' + cmp BYTE [rdi],'-' + jne check_flag_end - inc rdi - ; rax still set + inc rdi + ; rax still set check_flag_loop: - ; check null byte - mov cl,[rdi] - cmp cl,0 - je check_flag_end + ; check null byte + mov cl,[rdi] + cmp cl,0 + je check_flag_end - ; check for u - cmp cl,'u' - jne check_flag_error + ; check for u + cmp cl,'u' + jne check_flag_error - mov rax,1 - inc rdi - jmp check_flag_loop + mov rax,1 + inc rdi + jmp check_flag_loop check_flag_error: - push rdi ; arg + i - call start_error + push rdi ; arg + i + call start_error - ; message - mov rax,SYS_write - mov rdi,FD_stderr - mov rsi,arg_error_text - mov rdx,arg_error_text_len - syscall + ; message + mov rax,SYS_write + mov rdi,FD_stderr + mov rsi,arg_error_text + mov rdx,arg_error_text_len + syscall - ; character - mov rax,SYS_write - mov rdi,FD_stderr - pop rsi ; arg + i - mov rdx,1 - syscall + ; character + mov rax,SYS_write + mov rdi,FD_stderr + pop rsi ; arg + i + mov rdx,1 + syscall - call end_error + call end_error - mov rdi,1 - jmp exit + mov rdi,1 + jmp exit check_flag_end: - ret + ret ;; print exec_name and a colon_space -start_error: ; void start_error(void) - mov rdi,[exec_name] - call strlen - mov rdx,rax - mov rax,SYS_write - mov rdi,FD_stderr - mov rsi,[exec_name] - syscall +start_error: ; void start_error(void) + mov rdi,[exec_name] + call strlen + mov rdx,rax + mov rax,SYS_write + mov rdi,FD_stderr + mov rsi,[exec_name] + syscall - mov rax,SYS_write - mov rdi,FD_stderr - mov rsi,colon_space - mov rdx,colon_space_len - syscall - ret + mov rax,SYS_write + mov rdi,FD_stderr + mov rsi,colon_space + mov rdx,colon_space_len + syscall + ret ;; print newline -end_error: ; void end_error(void) - mov rax,SYS_write - mov rdi,FD_stderr - mov rsi,newline_ptr - mov rdx,1 - syscall - ret +end_error: ; void end_error(void) + mov rax,SYS_write + mov rdi,FD_stderr + mov rsi,newline_ptr + mov rdx,1 + syscall + ret -streql: ; bool streql(const char *s1, const char *s2) - ; check if both are zero - mov cl,[rdi] ; s1[i] - or cl,[rsi] - jz streql_true +streql: ; bool streql(const char *s1, const char *s2) + ; check if both are zero + mov cl,[rdi] ; s1[i] + or cl,[rsi] + jz streql_true - ; check if equal - mov cl,[rdi] - xor cl,[rsi] - jnz streql_false + ; check if equal + mov cl,[rdi] + xor cl,[rsi] + jnz streql_false - inc rdi - inc rsi - jmp streql + inc rdi + inc rsi + jmp streql streql_true: - mov rax,1 - ret + mov rax,1 + ret streql_false: - xor rax,rax - ret + xor rax,rax + ret -exit: ; NORETURN void exit(int status) - mov rax,SYS_exit - syscall +exit: ; NORETURN void exit(int status) + mov rax,SYS_exit + syscall -strlen: ; uint64 strlen(const char *str) - mov rax,rdi +strlen: ; uint64 strlen(const char *str) + mov rax,rdi strlen_loop: - cmp BYTE [rax],0 - je strlen_end - inc rax - jmp strlen_loop + cmp BYTE [rax],0 + je strlen_end + inc rax + jmp strlen_loop strlen_end: - sub rax,rdi - ret + sub rax,rdi + ret section .bss - exec_name resq 1 - read_buff resb BUFFER_SIZE + exec_name resq 1 + read_buff resb BUFFER_SIZE section .data - dash_str db "-",0x0 - colon_space db ": " - colon_space_len equ $ - colon_space - newline_ptr db 0xA - stdin_name db "",0x0 - arg_error_text db "unknown flag: " - arg_error_text_len equ $ - arg_error_text - read_error_text db "read error: " - read_error_text_len equ $ - read_error_text - open_error_text db "could not open file for reading: " - open_error_text_len equ $ - open_error_text + dash_str db "-",0x0 + colon_space db ": " + colon_space_len equ $ - colon_space + newline_ptr db 0xA + stdin_name db "",0x0 + arg_error_text db "unknown flag: " + arg_error_text_len equ $ - arg_error_text + read_error_text db "read error: " + read_error_text_len equ $ - read_error_text + open_error_text db "could not open file for reading: " + open_error_text_len equ $ - open_error_text diff --git a/freebsd.s b/freebsd.s deleted file mode 100644 index f66b3a5..0000000 --- a/freebsd.s +++ /dev/null @@ -1,12 +0,0 @@ -;; -*- mode: nasm -*- -;; FreeBSD system calls -%define SYS_open 0x5 -%define SYS_close 0x6 -%define SYS_write 0x4 -%define SYS_read 0x3 -%define SYS_lseek 0x1de -%define SYS_exit 0x1 - -;; FreeBSD constants -%define O_RDONLY 0x0 -%define SEEK_SET 0x0 diff --git a/linux.s b/linux.s deleted file mode 100644 index 6e41ba4..0000000 --- a/linux.s +++ /dev/null @@ -1,12 +0,0 @@ -;; -*- mode: nasm -*- -;; Linux system calls -%define SYS_open 0x2 -%define SYS_close 0x3 -%define SYS_write 0x1 -%define SYS_read 0x0 -%define SYS_lseek 0x8 -%define SYS_exit 0x3c - -;; Linux constants -%define O_RDONLY 0x0 -%define SEEK_SET 0x0