.globl _start .option rvc # enable compressed instructions .data writebuf: .ascii "00000000: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | ................\n" .equ hexstart, 10 .equ hexend, hexstart+3*16 .equ charstart, hexend+3 .equ linelen, (. - writebuf) .equ readlen, 16 readbuf: .zero readlen .text _start: # set up the gp register so that relaxed loads work .option push .option norelax la gp, __global_pointer$ .option pop # fd in s6 # data offset in s7 li s6, 0 li s7, 0 #0xabad1dea loop: li a7, 63 # sys_read mv a0, s6 # fd la a1, readbuf # pointer to buffer li a2, readlen # 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 li t5, 10 la s0, writebuf .macro hexnibble src, shift, dest slli t1, \src, (64-\shift-4) # put high nibble of s7 in t1 srli t1, t1, 64-4 addi t2, t1, 0x30 # convert to decimal digit bgt t5, t1, 0f # if digit >= 10, use switch to alpha addi t2, t1, 0x61-10 0: # copy digit to writebuf sb t2, \dest .endm .macro hexbyte src, shift, dest hexnibble \src, (\shift+4), \dest hexnibble \src, \shift, 1+\dest .endm hexbyte s7, 24, 0(s0) hexbyte s7, 16, 2(s0) hexbyte s7, 8, 4(s0) hexbyte s7, 0, 6(s0) la s1, readbuf # it's perfectly fine to process more # bytes than we read here, since the buffer # sizes are both fixed .macro inpbyte srcindex, dstindex lbu t0, \srcindex(s1) hexbyte t0, 0, \dstindex(s0) .endm # TODO: load 8 bytes at a time # (need a way to check endianness) inpbyte 0, 10 inpbyte 1, 13 inpbyte 2, 16 inpbyte 3, 19 inpbyte 4, 22 inpbyte 5, 25 inpbyte 6, 28 inpbyte 7, 31 inpbyte 8, 35 inpbyte 9, 38 inpbyte 10, 41 inpbyte 11, 44 inpbyte 12, 47 inpbyte 13, 50 inpbyte 14, 53 inpbyte 15, 56 li t0, 0 li t4, 0x7e-0x20 # the ascii printable range is 0x20-0x7e # # 0123456789ABCDEF # 20 !"#$%&'()*+,-./ # 30 0123456789:;<=>? # 40 @ABCDEFGHIJKLMNO # 50 PQRSTUVWXYZ[\]^_ # 60 `abcdefghijklmno # 70 pqrstuvwxyz{|}~ printable_loop: add t1, s1, t0 lbu t2, 0(t1) addi t3, t2, -0x20 bleu t3, t4, 0f li t2, 0x2e # '.' 0: add t1, s0, t0 sb t2, 61(t1) addi t0, t0, 1 blt t0, a0, printable_loop li t0, readlen blt a0, t0, fixup mv s0, a0 # save length read add s7, s7, s0 # file offset += s0 li a7, 64 # sys_write li a0, 1 # fd = stdout la a1, writebuf # pointer to string li a2, linelen # size of data ecall bltz a0, error j loop fixup: # we read <16 bytes, so we need to # 1) replace the hex bytes >a0 with spaces # 2) adjust the line length # 3) print it add t0, a0, a0 # t0 = len*3 add t0, t0, a0 addi t0, t0, hexstart add t0, s0, t0 addi t1, s0, hexend li t2, 0x20 1: sb t2, 0(t0) addi t0, t0, 1 blt t0, t1, 1b addi t0, a0, charstart add t1, t0, s0 li t2, 0xa # \n sb t2, 0(t1) li a7, 64 # sys_write li a0, 1 # fd = stdout la a1, writebuf # pointer to string addi a2, t0, 1 # size of data ecall bltz a0, error j done error: li a7, 93 # exit li a0, 1 ecall done: li a7, 93 # exit li a0, 0 ecall