40 lines
1.5 KiB
C
40 lines
1.5 KiB
C
// hello.c
|
|
// Minimal RISC-V Linux program without the C library.
|
|
// It uses direct system calls via the ECALL instruction.
|
|
//
|
|
// System call numbers for RISC-V Linux:
|
|
// __NR_write = 64
|
|
// __NR_exit = 93
|
|
//
|
|
// Compile this program with:
|
|
// riscv64-unknown-elf-gcc -nostdlib -static -O2 -o hello hello.c
|
|
|
|
// _start is the entry point when not using the standard C runtime.
|
|
void _start() {
|
|
// Define the message to print.
|
|
const char msg[] = "Hello, world!\n";
|
|
|
|
// --- Write "Hello, world!\n" to stdout ---
|
|
// For the write(2) system call:
|
|
// a0: file descriptor (1 for stdout)
|
|
// a1: pointer to the message
|
|
// a2: length of the message (without the null terminator)
|
|
// a7: system call number (__NR_write, which is 64)
|
|
register long a0 asm("a0") = 1; // file descriptor (stdout)
|
|
register const char *a1 asm("a1") = msg; // pointer to message
|
|
register long a2 asm("a2") = sizeof(msg) - 1; // message length
|
|
register long a7 asm("a7") = 64; // syscall number: write
|
|
asm volatile ("ecall" : : "r"(a0), "r"(a1), "r"(a2), "r"(a7));
|
|
|
|
// --- Exit the program ---
|
|
// For the exit(2) system call:
|
|
// a0: exit code (0 for success)
|
|
// a7: system call number (__NR_exit, which is 93)
|
|
register long exit_code asm("a0") = 0;
|
|
register long a7_exit asm("a7") = 93; // syscall number: exit
|
|
asm volatile ("ecall" : : "r"(exit_code), "r"(a7_exit));
|
|
|
|
// We should never reach this point.
|
|
while (1) {}
|
|
}
|