176 lines
3.5 KiB
ArmAsm
176 lines
3.5 KiB
ArmAsm
.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
|
|
|
|
|