Initial commit
This commit is contained in:
parent
a8bf8841c2
commit
6c6bed6c7e
435
cat.s
435
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 "<stdin>",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 "<stdin>",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
|
||||
|
12
freebsd.s
12
freebsd.s
@ -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
|
Loading…
Reference in New Issue
Block a user