commit 706e95f994b9d474d9a784683273b55a63c24b2f
parent d4f6abb9a55834c28d95bb2c6d951ec897606c0d
Author: evenfri <evenfri256@gmail.com>
Date: Sun, 2 Aug 2026 22:46:02 +0800
feat: syscalls, test directory
Diffstat:
11 files changed, 132 insertions(+), 9 deletions(-)
diff --git a/boot.asm b/boot.asm
@@ -20,16 +20,25 @@ stack_top:
section .text
global _start
+extern multiboot
extern start_kernel
_start:
; setup stack
mov esp, stack_top
- ; enter the high-level kernel
+ ; set arguments
push ebx
push eax
+ call multiboot
+
+ ; reset arguments
+ add esp, 8
+ xor eax, eax
+ xor ebx, ebx
+
+ ; enter the high-level kernel
call start_kernel
cli
diff --git a/dat.h b/dat.h
@@ -7,7 +7,7 @@
/* vga */
#define vga_width 80
#define vga_height 25
-#define vga_start 0xb8000
+#define vga_start 0xb8000
#define vga_ctrl 0x3d4
#define vga_data 0x3d5
@@ -62,4 +62,8 @@ typedef void (*int_handler)();
#define stdin 0
#define stdout 1
+/* syscalls */
+#define sys_read 0
+#define sys_write 1
+
#endif /* dat_h */
diff --git a/fns.h b/fns.h
@@ -57,4 +57,7 @@ void tty_write(const char* data, size_t size);
size_t vfs_read(unsigned int fd, void *buf, size_t size);
size_t vfs_write(unsigned int fd, void *buf, size_t size);
+/* syscall */
+void syscall_init();
+
#endif /* fns_h */
diff --git a/init.c b/init.c
@@ -2,6 +2,9 @@
#include <fns.h>
#include <keyboard/keyboard.h>
+extern void test_syscall_write();
+extern size_t test_syscall_read();
+
void multiboot(uint32_t magic, multiboot_info_t *mbi) {
if (magic != MULTIBOOT_BOOTLOADER_MAGIC) {
return;
@@ -19,6 +22,9 @@ void init() {
idt_init();
vfs_write(stdout, "idt initialized\n", 16);
+ syscall_init();
+ vfs_write(stdout, "syscalls initialized\n", 21);
+
keyboard_init();
vfs_write(stdout, "keyboard initialized\n", 21);
}
@@ -36,8 +42,7 @@ void bin_init_prog() {
}
}
-void start_kernel(uint32_t magic, multiboot_info_t *mbi) {
- multiboot(magic, mbi);
+void start_kernel() {
init();
bin_init_prog();
diff --git a/mkfile b/mkfile
@@ -7,8 +7,8 @@ cc = ./build/cc
ld = ./build/ld
ar = ./build/ar
-ldflags = keyboard/built-in.a
-dirs = keyboard
+ldflags = keyboard/built-in.a test/built-in.a
+dirs = keyboard test
ofiles = boot.$o \
vga.$o \
@@ -17,6 +17,8 @@ ofiles = boot.$o \
ints.$o \
tty.$o \
vfs.$o \
+ syscall_entry.$o \
+ syscall.$o \
init.$o \
strlen.$o
diff --git a/qemu.sh b/qemu.sh
@@ -2,6 +2,8 @@
set -e
kernel_bin="o.kernel"
+mem="4M"
-qemu-system-i386 -kernel "$kernel_bin"
-
+exec qemu-system-i386 \
+ -m "$mem" \
+ -kernel "$kernel_bin" \
diff --git a/syscall.c b/syscall.c
@@ -0,0 +1,20 @@
+#include <dat.h>
+#include <fns.h>
+
+extern void syscall_asm();
+
+void syscall_init() {
+ idt_register(0x80, syscall_asm);
+}
+
+int syscall_handler(int num, int arg1, int arg2,
+ int arg3, int arg4, int arg5) {
+ switch (num) {
+ case sys_read:
+ return vfs_read(arg1, (void*) arg2, arg3);
+ case sys_write:
+ return vfs_write(arg1, (void*) arg2, arg3);
+ default:
+ return -1;
+ }
+}
diff --git a/syscall_entry.asm b/syscall_entry.asm
@@ -0,0 +1,29 @@
+bits 32
+
+section .text
+global syscall_asm
+
+extern syscall_handler
+
+syscall_asm:
+ ; save 32-bits regs
+ pushad
+
+ push edi ; arg5
+ push esi ; arg4
+ push edx ; arg3
+ push ecx ; arg2
+ push ebx ; arg1
+ push eax ; num
+
+ sti
+ call syscall_handler
+ cli
+
+ ; clear stack
+ add esp, 24
+ mov [esp + 28], eax
+
+ popad
+ iret
+
diff --git a/test/mkfile b/test/mkfile
@@ -0,0 +1,12 @@
+<$kernel/build/mkhdr
+
+as = ../build/as
+cc = ../build/cc
+ar = ../build/ar
+
+ofiles = syscalls.$o \
+
+lib = built-in.a
+
+<$kernel/build/mklib
+<$kernel/build/mkcommon
diff --git a/test/syscalls.c b/test/syscalls.c
@@ -0,0 +1,38 @@
+#include <stddef.h>
+#include <dat.h>
+
+typedef long ssize_t;
+
+#define syscall3(n, arg1, arg2, arg3) ({ \
+ long ret; \
+ asm volatile ( \
+ "int $0x80" \
+ : "=a"(ret) \
+ : "a"(n), "b"(arg1), "c"(arg2), "d"(arg3) \
+ : "memory" \
+ ); \
+ ret; \
+})
+
+size_t write(int fd, void *buf, size_t size) {
+ long ret = syscall3(sys_write, fd, buf, size);
+ return ret;
+}
+
+size_t read(int fd, void *buf, size_t size) {
+ long ret = syscall3(sys_read, fd, buf, size);
+ return ret;
+}
+
+size_t test_syscall_read() {
+ char c;
+ size_t bytes = read(stdin, &c, 1);
+
+ if (bytes > 0) {
+ write(stdout, &c, 1);
+ } else {
+ asm volatile("hlt");
+ }
+
+ return bytes;
+}
diff --git a/vga.c b/vga.c
@@ -1,4 +1,3 @@
-#include <stdint.h>
#include <dat.h>
#include <fns.h>