diff --git a/README.md b/README.md new file mode 100644 index 0000000..074d397 --- /dev/null +++ b/README.md @@ -0,0 +1,12 @@ +# Risc-V Assembly Language Programming + +## Resources + +- [RISC-V Guru](https://risc-v.guru/) and [direct link to the instruction set](https://risc-v.guru/instructions/) +- [RISC-V Greehsheet](https://raw.githubusercontent.com/rswinkle/riscv_book/master/references/riscv_greensheet.pdf) and its [large version](https://raw.githubusercontent.com/rswinkle/riscv_book/master/references/riscv_greensheet_large.pdf) +- [RISC-V ISA Manual](https://riscv.org/wp-content/uploads/2017/05/riscv-spec-v2.2.pdf) +- [RISC-V Specifications](https://riscv.org/technical/specifications/) + +### Misc + +- [RISC-V Assembly Language Programming](https://github.com/rswinkle/riscv_book/) diff --git a/end.s b/end.s new file mode 100644 index 0000000..07b6e36 --- /dev/null +++ b/end.s @@ -0,0 +1,19 @@ +# Just print the word 'exit' to the address 0x10000000 +.globl end +end: + addi a0, x0, 0x65 # 'e' + li a1, 0x10000000 + sb a0, (a1) + + addi a0, x0, 0x78 # 'x' + sb a0, (a1) + + addi a0, x0, 0x69 # 'i' + sb a0, (a1) + + addi a0, x0, 0x74 # 't' + sb a0, (a1) + + addi a0, x0, 0x0A + sb a0, (a1) # '\n' + ret \ No newline at end of file diff --git a/hello.s b/hello.s deleted file mode 100644 index 1a6b2b7..0000000 --- a/hello.s +++ /dev/null @@ -1,16 +0,0 @@ -.section .text -.globl _hello - -_hello: - # Write the string "Hello, World!\n" to stdout - la a0, msg # Load the address of the string into a0 - li a7, 4 # syscall number for write - li a1, 13 # Length of the string - li a2, 1 # File descriptor: stdout - ecall # Make the system call to write - - ret # Return from the function - -.section .data -msg: - .ascii "Hello, World!\n" diff --git a/link.ld b/link.ld new file mode 100644 index 0000000..c5a85b0 --- /dev/null +++ b/link.ld @@ -0,0 +1,17 @@ +MEMORY { + SRAM (rwx) : ORIGIN = 0x20000000, LENGTH = 1024 + DRAM (rwx) : ORIGIN = 0x80000000, LENGTH = 1024 +} + +SECTIONS { + .text : { + main.o(.text.*) + *(.text) + } > DRAM + .data : { + *(.data) + } > DRAM AT > SRAM + .bss : { + *(.bss) + } > DRAM +} diff --git a/main.s b/main.s index faa2533..cbdd0b4 100644 --- a/main.s +++ b/main.s @@ -1,12 +1,69 @@ -.section .text -.globl _start +# Define variables +.data +.align 4 + num1: .word 5 # First number + num2: .word 7 # Second number + result: .word 0 # Variable to store the result + msg: .ascii "Hello, World!\n" + array: .space 100 # 100 bytes of space -_start: - # Call the hello function - lui a0, %hi(_hello) # Load upper immediate of _hello address - addi a0, a0, %lo(_hello) # Add lower immediate of _hello address - jalr ra, a0, 0 # Jump and link to _hello, ra is return address +# Main program entry point +.globl start +.text +start: + call test_routine + call hello_manual + # call hello # This doesn't work + call end + ebreak - # Exit the program - li a7, 10 # syscall number for exit - ecall # Make the system call to exit +# Arbitrary test routine +test_routine: + la a0, num1 # Load the address of num1 into register a6 + li a1, 10 # Load the value 10 into register a5 + xori a2, a1, 0x1 # Calculate the value of a2 + sw a1, 0(a0) # Store the value in memory + ret + +# Prints "hello" manually +hello_manual: + addi a0, x0, 0x68 + li a1, 0x10000000 + sb a0, (a1) # 'h' + + addi a0, x0, 0x65 + sb a0, (a1) # 'e' + + addi a0, x0, 0x6C + sb a0, (a1) # 'l' + + addi a0, x0, 0x6C + sb a0, (a1) # 'l' + + addi a0, x0, 0x6F + sb a0, (a1) # 'o' + + addi a0, x0, 0x0A + sb a0, (a1) # '\n' + ret + +# Is supposed to print "Hello, World!\n" to stdout via ecall, but doesn't work +hello: + # Write the string "Hello, World!\n" to stdout + la a0, msg # Load the address of the string into a0 + li a7, 4 # syscall number for write + li a1, 13 # Length of the string + li a2, 1 # File descriptor: stdout + ecall # Make the system call to write + ret # Return from the function + +# Another routine, presumably written for the rars emulator? +hello2: + li a0, 0x1 + la a1, msg + li a2, 13 + li a7, 64 + ecall + +# To avoid the program from exiting +loop: j loop \ No newline at end of file diff --git a/makefile b/makefile index 1f81cfc..33620fb 100644 --- a/makefile +++ b/makefile @@ -10,8 +10,10 @@ SIZE = ${CROSS}-size TARGET = bin.elf # QEMU command and flags -QEMU = qemu-riscv64-static -QEMU_FLAGS = +# QEMU = qemu-riscv64-static +QEMU = qemu-system-riscv64 +QEMU_FLAGS += --machine virt# # Use the virt machine +QEMU_FLAGS += --nographic# # No graphical output # Flags for compiler and assembler CFLAGS += -static# # Use static linking @@ -23,6 +25,13 @@ CFLAGS += -march=rv64i # Use RV64I ISA, i.e., integer only CFLAGS += -mabi=lp64 # Use LP64 ABI, i.e., 64-bit longs and pointers, 32-bit ints CFLAGS += -Os# # Optimize for size +LDFLAGS += -T link.ld # Use the linker script +LDFLAGS += --no-dynamic-linker +LDFLAGS += -m elf64lriscv +LDFLAGS += -static +LDFLAGS += -nostdlib +LDFLAGS += -s + # Use GC=0 to disable garbage collection ifneq ($(GC), 0) CFLAGS += -ffreestanding @@ -43,7 +52,7 @@ OBJS := $(AS_SRCS:.s=.o) # Default target all: $(OBJS) - @$(CC) $(CFLAGS) -o $(TARGET) $(OBJS) + @$(LD) $(LDFLAGS) -o $(TARGET) $(OBJS) @echo "LD $(OBJS)" # Compile assembly sources @@ -52,8 +61,9 @@ all: $(OBJS) @echo "CC $<" # Run the binary in QEMU -run: all - $(QEMU) $(QEMU_FLAGS) ./$(TARGET) +run: all + @echo "To exit: Ctrl+A, X" + @$(QEMU) $(QEMU_FLAGS) -bios $(TARGET) # View the text section of the binary inspect: all