Last active
July 22, 2025 14:19
-
-
Save rrampage/c666e4bbd3a94d53847808bdd28d140c to your computer and use it in GitHub Desktop.
Tiny ARM64 ELF kernel
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
ARM64 kernel to echo user input | |
Adapted from: | |
- http://wiki.osdev.org/QEMU_AArch64_Virt_Bare_Bones | |
- https://krinkinmu.github.io/2020/11/29/PL011.html | |
- https://wiki.osdev.org/Raspberry_Pi_Bare_Bones (getc and putc) | |
Compile: `as -o boot.o boot.S && ld -s -o asmkernel boot.o` | |
Run on QEMU using: `qemu-system-aarch64 -machine virt -cpu max -nographic -kernel asmkernel.elf` | |
*/ | |
.equ UART_ADDR, 0x9000000 // UART base + dest | |
.equ UART_FLAG_REG, 0x9000018 | |
.equ UART_TXFF, 0x20 // transmit fifo full | |
.equ UART_RXFE, 0x10 // receive fifo empty | |
.data | |
msg: | |
.ascii "Hello World!\n"; | |
len = . - msg | |
.text | |
.global _start | |
/* | |
x20 -> UART address for reading/writing bytes | |
x19 -> UART flag address for checking status before r/w | |
w3 -> contains state of flag, not used for anything else | |
w4 -> byte read from/ to be written to UART | |
*/ | |
_start: | |
mov x20, UART_ADDR | |
add x19, x20, #0x18 // move flag reg | |
adr x1, msg | |
ldr x2, =len | |
bl print | |
bl echo | |
b . | |
getc: | |
ldrb w3, [x19] | |
and w3, w3, #UART_RXFE | |
cbnz w3, getc | |
ldrb w4, [x20] | |
ret | |
putc: | |
ldrb w3, [x19] | |
and w3, w3, #UART_TXFF | |
cbnz w3, putc | |
strb w4, [x20] | |
ret | |
print: | |
mov x5, #0 | |
loop: | |
cmp x5, x2 | |
b.ge done | |
ldrb w6, [x1,x5] | |
strb w6, [x20] | |
add x5, x5, 1 | |
b loop | |
done: | |
ret | |
echo: | |
bl getc | |
cmp w4, #0x08 // backspace | |
b.ne del | |
b backspace | |
del: | |
cmp w4, #0x7f // del | |
b.ne crlf | |
mov w4, #0x08 // backspace | |
backspace: | |
bl putc | |
mov w4, #0x20 // space | |
bl putc | |
mov w4, #0x08 // backspace | |
bl putc | |
crlf: | |
cmp w4, #0x0D // CR -> putc 'CR' + putc 'LF' | |
b.ne just_echo | |
bl putc | |
mov w4, #0x0A | |
just_echo: | |
bl putc | |
b echo |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment