asm-cat/cat.s

307 lines
5.7 KiB
ArmAsm
Raw Normal View History

2022-08-28 14:29:25 -07:00
;; -*- mode: nasm -*-
2022-09-17 18:09:28 -07:00
%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
2022-08-28 14:29:25 -07:00
%define FD_stderr 2
%define FD_stdout 1
%define FD_stdin 0
%define BUFFER_SIZE 2048
section .text
global _start
_start:
2022-09-17 18:09:28 -07:00
pop rax ; argc
pop QWORD [exec_name] ; argv[0]
2022-08-28 14:29:25 -07:00
check_arg_loop:
2022-09-17 18:09:28 -07:00
mov rdi,[rsp] ; argv[i]
; check for null
cmp rdi,0
je print_stdin_and_exit
2022-08-28 14:29:25 -07:00
2022-09-17 18:09:28 -07:00
; check for flags
call check_flag
cmp rax,0
je print_files ; no more flags
2022-08-28 14:29:25 -07:00
2022-09-17 18:09:28 -07:00
pop rdi ; remove argv[i] (a flag)
jmp check_arg_loop
2022-08-28 14:29:25 -07:00
print_files:
2022-09-17 18:09:28 -07:00
mov rdi,[rsp] ; argv[i]
cmp rdi,0
je print_files_end
2022-08-28 14:29:25 -07:00
2022-09-17 18:09:28 -07:00
; check if argv[i] is '-'
mov rsi,dash_str
call streql
cmp rax,0
jne print_files_stdin
2022-08-28 14:29:25 -07:00
2022-09-17 18:09:28 -07:00
; open file
mov rdi,[rsp] ; argv[i]
call open_file
2022-08-28 14:29:25 -07:00
2022-09-17 18:09:28 -07:00
; print file
mov rdi,rax
pop rsi ; argv[i]
call print_file
2022-08-28 14:29:25 -07:00
2022-09-17 18:09:28 -07:00
jmp print_files
2022-08-28 14:29:25 -07:00
print_files_stdin:
2022-09-17 18:09:28 -07:00
pop rdi ; argv[i]
mov rdi,FD_stdin
mov rsi,stdin_name
call print_file
2022-08-28 14:29:25 -07:00
2022-09-17 18:09:28 -07:00
; rewind stdin
2022-08-28 14:29:25 -07:00
mov rax,SYS_lseek
2022-09-17 18:09:28 -07:00
mov rdi,FD_stdin
mov rsi,0
mov rdx,SEEK_SET
syscall
2022-08-28 14:29:25 -07:00
2022-09-17 18:09:28 -07:00
jmp print_files
2022-08-28 14:29:25 -07:00
print_files_end:
2022-09-17 18:09:28 -07:00
xor rdi,rdi
jmp exit
2022-08-28 14:29:25 -07:00
2022-09-17 18:09:28 -07:00
open_file: ; int open_file(const char *path)
push rdi ; path
2022-08-28 14:29:25 -07:00
2022-09-17 18:09:28 -07:00
; open file
mov rax,SYS_open
; rdi already set
mov rsi,O_RDONLY
syscall
2022-08-28 14:29:25 -07:00
2022-09-17 18:09:28 -07:00
; check return
cmp rax,0
jl open_error
2022-08-28 14:29:25 -07:00
2022-09-17 18:09:28 -07:00
pop rdi ; path
ret
2022-08-28 14:29:25 -07:00
open_error:
2022-09-17 18:09:28 -07:00
call start_error
2022-08-28 14:29:25 -07:00
2022-09-17 18:09:28 -07:00
; message
mov rax,SYS_write
mov rdi,FD_stderr
mov rsi,open_error_text
mov rdx,open_error_text_len
syscall
2022-08-28 14:29:25 -07:00
2022-09-17 18:09:28 -07:00
; detail
mov rdi,[rsp] ; path
call strlen
2022-08-28 14:29:25 -07:00
2022-09-17 18:09:28 -07:00
mov rdx,rax
mov rax,SYS_write
mov rdi,FD_stderr
pop rsi ; path
syscall
2022-08-28 14:29:25 -07:00
2022-09-17 18:09:28 -07:00
call end_error
2022-08-28 14:29:25 -07:00
2022-09-17 18:09:28 -07:00
mov rdi,1
jmp exit
2022-08-28 14:29:25 -07:00
print_stdin_and_exit:
2022-09-17 18:09:28 -07:00
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
2022-08-28 14:29:25 -07:00
print_file_loop:
2022-09-17 18:09:28 -07:00
mov rax,SYS_read
mov rdi,[rsp + 8] ; fd
mov rsi,read_buff
mov rdx,BUFFER_SIZE
syscall
2022-08-28 14:29:25 -07:00
2022-09-17 18:09:28 -07:00
; check error
cmp rax,0
jl read_file_error
2022-08-28 14:29:25 -07:00
2022-09-17 18:09:28 -07:00
; no more bytes
je print_file_end
2022-08-28 14:29:25 -07:00
2022-09-17 18:09:28 -07:00
; print message
mov rdx,rax
mov rax,SYS_write
mov rdi,FD_stdout
mov rsi,read_buff
syscall
2022-08-28 14:29:25 -07:00
2022-09-17 18:09:28 -07:00
jmp print_file_loop
2022-08-28 14:29:25 -07:00
print_file_end:
2022-09-17 18:09:28 -07:00
pop rsi ; name
pop rdi ; fd
ret
2022-08-28 14:29:25 -07:00
read_file_error:
2022-09-17 18:09:28 -07:00
call start_error
2022-08-28 14:29:25 -07:00
2022-09-17 18:09:28 -07:00
; message
mov rax,SYS_write
mov rdi,FD_stderr
mov rsi,read_error_text
mov rdx,read_error_text_len
syscall
2022-08-28 14:29:25 -07:00
2022-09-17 18:09:28 -07:00
; detail
mov rdi,[rsp] ; name
call strlen
2022-08-28 14:29:25 -07:00
2022-09-17 18:09:28 -07:00
mov rdx,rax
mov rax,SYS_write
mov rdi,FD_stderr
pop rsi ; name
syscall
2022-08-28 14:29:25 -07:00
2022-09-17 18:09:28 -07:00
call end_error
2022-08-28 14:29:25 -07:00
2022-09-17 18:09:28 -07:00
mov rdi,1
jmp exit
2022-08-28 14:29:25 -07:00
;; check arg for -u, exit if unknown flag
;; return 1 if found, 0 otherwise
2022-09-17 18:09:28 -07:00
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
2022-08-28 14:29:25 -07:00
check_flag_loop:
2022-09-17 18:09:28 -07:00
; check null byte
mov cl,[rdi]
cmp cl,0
je check_flag_end
; check for u
cmp cl,'u'
jne check_flag_error
mov rax,1
inc rdi
jmp check_flag_loop
2022-08-28 14:29:25 -07:00
check_flag_error:
2022-09-17 18:09:28 -07:00
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
; character
mov rax,SYS_write
mov rdi,FD_stderr
pop rsi ; arg + i
mov rdx,1
syscall
call end_error
mov rdi,1
jmp exit
2022-08-28 14:29:25 -07:00
check_flag_end:
2022-09-17 18:09:28 -07:00
ret
2022-08-28 14:29:25 -07:00
;; print exec_name and a colon_space
2022-09-17 18:09:28 -07:00
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
2022-08-28 14:29:25 -07:00
;; print newline
2022-09-17 18:09:28 -07:00
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
; check if equal
mov cl,[rdi]
xor cl,[rsi]
jnz streql_false
inc rdi
inc rsi
jmp streql
2022-08-28 14:29:25 -07:00
streql_true:
2022-09-17 18:09:28 -07:00
mov rax,1
ret
2022-08-28 14:29:25 -07:00
streql_false:
2022-09-17 18:09:28 -07:00
xor rax,rax
ret
2022-08-28 14:29:25 -07:00
2022-09-17 18:09:28 -07:00
exit: ; NORETURN void exit(int status)
mov rax,SYS_exit
syscall
2022-08-28 14:29:25 -07:00
2022-09-17 18:09:28 -07:00
strlen: ; uint64 strlen(const char *str)
mov rax,rdi
2022-08-28 14:29:25 -07:00
strlen_loop:
2022-09-17 18:09:28 -07:00
cmp BYTE [rax],0
je strlen_end
inc rax
jmp strlen_loop
2022-08-28 14:29:25 -07:00
strlen_end:
2022-09-17 18:09:28 -07:00
sub rax,rdi
ret
2022-08-28 14:29:25 -07:00
section .bss
2022-09-17 18:09:28 -07:00
exec_name resq 1
read_buff resb BUFFER_SIZE
2022-08-28 14:29:25 -07:00
section .data
2022-09-17 18:09:28 -07:00
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