riscv-utils/echo.s

103 lines
1.7 KiB
ArmAsm

.globl _start
.option rvc # enable compressed instructions
.option norelax
.section .rodata
space: .ascii " "
newline: .ascii "\n"
.text
_start:
# arguments are passed on the stack:
# --bottom of stack--
# dd argc
# dd argv[0]
# dd ...
# dd 0
# dd envp[0]
# dd ...
# dd 0
ld s0, 0(sp) # get argc
add s1, sp, 8
# TODO: iovec
# allocate stack space for #argc iovecs
#slli t0, s0, 2
#sub tp, sp, t0
beqz s0, end
# skip argv[0]
addi s0, s0, -1
addi s1, s1, 8
beqz s0, end
# loop over argv
# write each argument
li s11, 0
mv s2, s0
la s8, space
loop:
# get argv[i]
slli t0, s11, 3
add t0, t0, s1
ld a1, 0(t0)
# check for null pointer, just in case
beqz a1, step
# compute length of string
mv t1, a1
strlen:
lbu t0, 0(t1)
addi t1, t1, 1
bnez t0, strlen
addi t1, t1, -1 # NUL
sub a2, t1, a1
li a7, 64 # sys_write
li a0, 1 # stdout
# a1 & a2 already set
ecall
bltz a0, write_error
# increment index
# if this was the last argument, break
addi s11, s11, 1
bge s11, s0, end
# not the last argument, so print a space and loop
li a7, 64 # sys_write
li a0, 1 # stdout
mv a1, s8 # space
li a2, 1 # size
ecall
bltz a0, write_error
j loop
step:
# increment index and loop
addi s11, s11, 1
blt s11, s0, loop
end:
# print a newline at the end,
# regardless of whether there were any arguments or not
li a7, 64 # sys_write
li a0, 1 # stdout
la a1, newline
li a2, 1 # size
ecall
bltz a0, write_error
li a7, 93 # exit
li a0, 0
ecall
write_error:
li a7, 93 # exit
li a0, 1
ecall