Compare commits
9 commits
9ff42d8fbc
...
7c0e113593
Author | SHA1 | Date | |
---|---|---|---|
![]() |
7c0e113593 | ||
![]() |
6e1839892a | ||
![]() |
8024135f25 | ||
![]() |
1712787e01 | ||
![]() |
279fc9b754 | ||
![]() |
868c032cbc | ||
![]() |
a63046569d | ||
![]() |
0e259f27bd | ||
![]() |
e681b848d5 |
6 changed files with 130 additions and 31 deletions
12
README.md
Normal file
12
README.md
Normal file
|
@ -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/)
|
19
end.s
Normal file
19
end.s
Normal file
|
@ -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
|
16
hello.s
16
hello.s
|
@ -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"
|
|
17
link.ld
Normal file
17
link.ld
Normal file
|
@ -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
|
||||||
|
}
|
77
main.s
77
main.s
|
@ -1,12 +1,69 @@
|
||||||
.section .text
|
# Define variables
|
||||||
.globl _start
|
.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:
|
# Main program entry point
|
||||||
# Call the hello function
|
.globl start
|
||||||
lui a0, %hi(_hello) # Load upper immediate of _hello address
|
.text
|
||||||
addi a0, a0, %lo(_hello) # Add lower immediate of _hello address
|
start:
|
||||||
jalr ra, a0, 0 # Jump and link to _hello, ra is return address
|
call test_routine
|
||||||
|
call hello_manual
|
||||||
|
# call hello # This doesn't work
|
||||||
|
call end
|
||||||
|
ebreak
|
||||||
|
|
||||||
# Exit the program
|
# Arbitrary test routine
|
||||||
li a7, 10 # syscall number for exit
|
test_routine:
|
||||||
ecall # Make the system call to exit
|
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
|
18
makefile
18
makefile
|
@ -10,8 +10,10 @@ SIZE = ${CROSS}-size
|
||||||
TARGET = bin.elf
|
TARGET = bin.elf
|
||||||
|
|
||||||
# QEMU command and flags
|
# QEMU command and flags
|
||||||
QEMU = qemu-riscv64-static
|
# QEMU = qemu-riscv64-static
|
||||||
QEMU_FLAGS =
|
QEMU = qemu-system-riscv64
|
||||||
|
QEMU_FLAGS += --machine virt# # Use the virt machine
|
||||||
|
QEMU_FLAGS += --nographic# # No graphical output
|
||||||
|
|
||||||
# Flags for compiler and assembler
|
# Flags for compiler and assembler
|
||||||
CFLAGS += -static# # Use static linking
|
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 += -mabi=lp64 # Use LP64 ABI, i.e., 64-bit longs and pointers, 32-bit ints
|
||||||
CFLAGS += -Os# # Optimize for size
|
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
|
# Use GC=0 to disable garbage collection
|
||||||
ifneq ($(GC), 0)
|
ifneq ($(GC), 0)
|
||||||
CFLAGS += -ffreestanding
|
CFLAGS += -ffreestanding
|
||||||
|
@ -43,7 +52,7 @@ OBJS := $(AS_SRCS:.s=.o)
|
||||||
|
|
||||||
# Default target
|
# Default target
|
||||||
all: $(OBJS)
|
all: $(OBJS)
|
||||||
@$(CC) $(CFLAGS) -o $(TARGET) $(OBJS)
|
@$(LD) $(LDFLAGS) -o $(TARGET) $(OBJS)
|
||||||
@echo "LD $(OBJS)"
|
@echo "LD $(OBJS)"
|
||||||
|
|
||||||
# Compile assembly sources
|
# Compile assembly sources
|
||||||
|
@ -53,7 +62,8 @@ all: $(OBJS)
|
||||||
|
|
||||||
# Run the binary in QEMU
|
# Run the binary in QEMU
|
||||||
run: all
|
run: all
|
||||||
$(QEMU) $(QEMU_FLAGS) ./$(TARGET)
|
@echo "To exit: Ctrl+A, X"
|
||||||
|
@$(QEMU) $(QEMU_FLAGS) -bios $(TARGET)
|
||||||
|
|
||||||
# View the text section of the binary
|
# View the text section of the binary
|
||||||
inspect: all
|
inspect: all
|
||||||
|
|
Loading…
Reference in a new issue