.globl _start .option rvc # enable compressed instructions #.option norelax .data sigaction: .dword segv # sa_handler .dword 0 # sa_flags .dword 0 # sa_mask .data buf: .zero 8 .text _start: # set up the gp register so that relaxed loads work .option norelax la gp, __global_pointer$ .option relax # the following is what the la instruction above gets expanded to, # but writing it out explicitly like this causes ld to segfault #auipc gp, %pcrel_hi(__global_pointer$) #addi gp, gp, %pcrel_lo(__global_pointer$) # set up a signal handler for SIGSEGV # XXX we don't actually need this because write will # return EFAULT if the address isn't mapped li a7, 134 # sys_rt_sigaction li a0, 11 # SIGSEGv la a1, sigaction # action li a2, 0 # oldact = NULL li a3, 8 # signal set size (bytes) ecall # save sp la s7, buf sd sp, 0(s7) # print sp li a7, 64 # sys_write li a0, 1 # fd = stdout mv a1, s7 # pointer to string li a2, 8 # size of data ecall bltz a0, write_error # round sp down to multiple of 512 # and move to s0 andi s0, sp, -512 loop: # print sp sd s0, 0(s7) li a7, 64 # sys_write li a0, 1 # fd = stdout mv a1, s7 # pointer to string li a2, 8 # size of data ecall bltz a0, write_error # print 512 bytes of stack li a7, 64 # sys_write li a0, 1 mv a1, s0 li a2, 512 ecall bltz a0, write_error # increment sp by 512 addi s0, s0, 512 beqz s0, segv j loop write_error: li a7, 93 # exit li a0, 1 ecall segv: li a7, 93 # exit li a0, 0 ecall