Initial commit
This commit is contained in:
parent
a8bf8841c2
commit
6c6bed6c7e
435
cat.s
435
cat.s
@ -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
|
||||||
|
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