diff --git a/Makefile b/Makefile index 1e3bdb3..de95d29 100644 --- a/Makefile +++ b/Makefile @@ -1,13 +1,13 @@ AS=riscv64-unknown-elf-as LD=riscv64-unknown-elf-ld -all: main.x +all: calc.elf hello.elf: hello.o $(LD) -m elf32lriscv $^ -o $@ -main.x: main.o exit.o - $(LD) -m elf32lriscv $^ -o main.x +calc.elf: calc.o + $(LD) -m elf32lriscv -T link.ld $^ -o $@ %.o : %.s $(AS) -mabi=ilp32e -march=rv32ec $< -o $@ diff --git a/README.md b/README.md index f604ebf..3fd9503 100644 --- a/README.md +++ b/README.md @@ -11,6 +11,14 @@ Notes riscv64-unknown-elf-objdump -D main.o +### List Symbols + + riscv64-unknown-elf-nm calc.o + +### List segment info + + readelf -l calc.elf + Resources --------- diff --git a/calc.s b/calc.s new file mode 100644 index 0000000..2b783d9 --- /dev/null +++ b/calc.s @@ -0,0 +1,110 @@ +# RISC-V assembly program implementing a calculator. + +.org 0 +# Provide program starting address to linker +.global _start + +/* newlib system calls */ +.set SYSEXIT, 93 +.set SYSWRITE, 64 + +.section .rodata +str: .ascii "Hello World!\n" + .set str_size, .-str +str2: .ascii "regdump\n" + .set str2_size, .-str2 + + +.section .bss +buf: .skip 20 # room for 20 byte string + # x10: ABCDEFG\n is 23 chars + +.section .data +buflen: .byte 0 # length of buf string + + +.text +_start: + li t1, 0 + li t2, 5 + + # dummy test for jal instruction +.L1: + jal x0, .L2 +.L2: + nop + +loop: + beq t1, t2, end + + li t0, SYSWRITE # "write" syscall + li a0, 1 # 1 = standard output (stdout) + la a1, str # load address of hello string + li a2, str_size # length of hello string + ecall # invoke syscall to print the string + addi t1, t1, 1 + j loop + +end: + # do some adding + li a0, 0x80000000 # 0.5 + li a1, 1 # 1 + li a2, 0x80000000 # 0.5 + li a3, 1 # 1 + jal add64 + #add t1, a0, 0 # copy a0 to t0 as end with overwrite it + jal regdump + + li t0, SYSEXIT # "exit" syscall + add a0, x0, 0 # Use 0 return code + ecall # invoke syscall to terminate the program + +# 64-bit integer addition +# arguments: +# a0: x lower 32 bits +# a1: x upper 32 bits +# a2: y lower 32 bits +# a3: y upper 32 bits +# return: +# a0: x+y lower 32 bits +# a1: x+y upper 32 bits +# +add64: + add a0, a0, a2 # add lower 32 bits + add t0, a1, a3 # add upper 32 bits + sltu t1, a0, a2 # if lower 32-bit sum < a2 then set t1=1 (carry bit) + add a1, t0, t1 # upper 32 bits of answer (upper sum + carry bit) + ret + + +# Print values of all registers (in hex) +# write syscall uses t0, a0, a1, a2 +regdump: + addi sp, sp, -16 # allocate stack space + sw a0, 12(sp) # save contents of a0 + sw a1, 8(sp) # save contents of a0 + sw a2, 4(sp) # save contents of a0 + sw t0, 0(sp) # save contents of a0 + + li t0, SYSWRITE # "write" syscall + li a0, 1 # 1 = standard output (stdout) + la a1, str2 # load address of hello string + li a2, str2_size # length of other string + ecall # invoke syscall to print the string + + # as a test load something into buf and print it + la a1, buf # load address of buf into a1 + li a0, 'h + sb a0, 0(a1) + li a0, '\n + sb a0, 1(a1) + li a2, 2 # length of buf + + li t0, SYSWRITE # "write" syscall + li a0, 1 # 1 = standard output (stdout) + # li a2, buflen # length of hello string + ecall # invoke syscall to print the string + + addi sp, sp, 16 # deallocate stack space + ret + diff --git a/link.ld b/link.ld new file mode 100644 index 0000000..4a3aaef --- /dev/null +++ b/link.ld @@ -0,0 +1,15 @@ +OUTPUT_ARCH( "riscv" ) + +ENTRY(_start) + +SECTIONS +{ + . = 0x0; + .text : { *(.text) } + /* Address warning: calc.elf has a LOAD segment with RWX permissions + * https://www.redhat.com/en/blog/linkers-warnings-about-executable-stacks-and-segments + */ + . = ALIGN (CONSTANT (COMMONPAGESIZE)); + .data : { *(.data) } + .bss : { *(.bss) } +}