From 6b66d832cfa03cd0c284f34584e280104bdf36b1 Mon Sep 17 00:00:00 2001 From: Andrew Ekstedt Date: Mon, 17 Apr 2023 00:27:28 -0700 Subject: [PATCH] add hexdump --- .gitignore | 1 + Makefile | 2 +- hexdump.s | 175 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 177 insertions(+), 1 deletion(-) create mode 100644 hexdump.s diff --git a/.gitignore b/.gitignore index fa0feeb..6b63016 100644 --- a/.gitignore +++ b/.gitignore @@ -3,3 +3,4 @@ /cat /printstack /env +/hexdump diff --git a/Makefile b/Makefile index 616c360..7808680 100644 --- a/Makefile +++ b/Makefile @@ -5,7 +5,7 @@ LD = $(TARGET)-ld .SUFFIXES: .PHONY: all -all: true false cat env +all: true false cat env hexdump #all: echo %: %.o diff --git a/hexdump.s b/hexdump.s new file mode 100644 index 0000000..b8c1e59 --- /dev/null +++ b/hexdump.s @@ -0,0 +1,175 @@ +.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 + +