Initial commit

This commit is contained in:
Alexander Rosenberg 2022-09-17 18:09:28 -07:00
parent a8bf8841c2
commit 6c6bed6c7e
Signed by: Zander671
GPG Key ID: 5FD0394ADBD72730
3 changed files with 220 additions and 239 deletions

435
cat.s
View File

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

View File

@ -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

12
linux.s
View File

@ -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