diff --git a/.gitignore b/.gitignore index c8a243a..e6db6af 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ /true /false +/cat diff --git a/Makefile b/Makefile index 096359b..c4f4d2f 100644 --- a/Makefile +++ b/Makefile @@ -4,8 +4,9 @@ LD = $(TARGET)-ld .SUFFIXES: -all: true false -#all: cat echo +.PHONY: all +all: true false cat +#all: echo %: %.o $(LD) -o $@ $< diff --git a/cat.s b/cat.s new file mode 100644 index 0000000..8e57ae0 --- /dev/null +++ b/cat.s @@ -0,0 +1,68 @@ +.globl _start +.option rvc # enable compressed instructions + +.data +sigaction_ignore: + .dword 1 # sa_handler = SIG_IGN + .dword 0 # sa_flags + .dword 0 # sa_mask + +.bss +.equ bufsize, 4<<10 +buf: .zero bufsize + +.text +_start: + # ignore SIGPIPE + li a7, 134 # sys_rt_sigaction + li a0, 13 # SIGPIPE + la a1, sigaction_ignore # action + li a2, 0 # oldact = NULL + # if this is a non-null pointer the kernel will + # return a copy of the old action to us, but we don't care + li a3, 8 # signal set size (bytes) + ecall + +# TODO: cat args +# TODO: error messages + +loop: + li a7, 63 # sys_read + li a0, 0 # fd = stdin + la a1, buf # pointer to buffer + li a2, bufsize # size of buffer + ecall + #li a0, 0 + + # return in a0 + # negative => error code + # positive => number of byte read + # zero => end of input + bltz a0, error + beqz a0, done + + mv s0, a0 + + li a7, 64 # sys_write + li a0, 1 # fd = stdout + la a1, buf # pointer to string + mv a2, s0 # size of data + ecall + + beq a0, s0, loop + # error, fall through + + # check for EPIPE + li t0, -32 + beq a0, t0, done # EPIPE + +error: + li a7, 93 # sys_exit + li a0, 1 # status code = failure + ecall + +done: + li a7, 93 # sys_exit + li a0, 0 # status code = success + ecall +