From 17ca59abe051b6e9f2b49c8cd9680320779cf47e Mon Sep 17 00:00:00 2001 From: Kitsu Date: Thu, 9 Dec 2021 02:18:30 +0300 Subject: [PATCH] Use C for syscalls --- Cargo.toml | 3 ++ build.rs | 8 +++++ src/lib.rs | 84 ++++++++++++++++++------------------------------- src/main.rs | 1 - src/sys.rs | 16 ++++++++++ src/syscalls.c | 54 +++++++++++++++++++++++++++++++ src/syscalls.o | Bin 0 -> 1336 bytes 7 files changed, 112 insertions(+), 54 deletions(-) create mode 100644 build.rs create mode 100644 src/sys.rs create mode 100644 src/syscalls.c create mode 100644 src/syscalls.o diff --git a/Cargo.toml b/Cargo.toml index 06e081f..ef353ff 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -12,3 +12,6 @@ lto = "thin" [dependencies] cstr_core = { version = "0.2.4", default-features = false, features = ["nightly"] } + +[build-dependencies] +cc = "1.0.72" diff --git a/build.rs b/build.rs new file mode 100644 index 0000000..3d1264e --- /dev/null +++ b/build.rs @@ -0,0 +1,8 @@ +fn main() { + println!("cargo:rerun-if-changed=src/syscalls.c"); + cc::Build::new() + .file("src/syscalls.c") + .flag("-fno-PIC") // for some reason `pic(false)` doesn't work + .static_flag(true) + .compile("syscalls"); +} diff --git a/src/lib.rs b/src/lib.rs index fe69ae6..36f0969 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,22 +1,8 @@ -#![feature(asm)] #![no_std] -macro_rules! syscall { - ($fn_no:literal) => {{ - let mut res: i32 = $fn_no; +mod sys; - asm!("int 0x40", inout("eax") res); - res - }}; - ($fn_no:literal, $($reg:tt)*) => {{ - let mut res: i32 = $fn_no; - asm!("int 0x40", - $($reg)*, - inout("eax") res, - ); - res - }} -} +pub use sys::*; #[derive(Clone, Copy)] pub struct Color(u8, u8, u8); @@ -29,9 +15,11 @@ impl Color { pub fn r(&self) -> u8 { self.0 } + pub fn g(&self) -> u8 { self.1 } + pub fn b(&self) -> u8 { self.2 } @@ -41,11 +29,6 @@ impl Color { } } -#[inline] -pub unsafe fn start_window_draw() { - syscall!(12, in("ebx") 1); -} - pub struct Dot { pub x: u32, pub y: u32, @@ -66,17 +49,21 @@ pub struct WindowParams<'a> { pub title: Option<&'a cstr_core::CStr>, } -#[inline] -pub unsafe fn define_window(start: Dot, width: u32, height: u32, params: WindowParams<'_>) { +pub fn define_window(start: Dot, width: u32, height: u32, params: WindowParams<'_>) { const RELATIVE_FLAG: u32 = 0x20; - syscall!( - 0, - in("ebx") start.x * 65536 + width, - in("ecx") start.y * 65536 + height, - in("edx") params.color.as_rgb_val() | - (RELATIVE_FLAG | (params.title.is_some() as u32) << 4 | params.kind as u32) << 24, - in("edi") params.title.map(|s| s.as_ptr()).unwrap_or_else(core::ptr::null) - ); + + unsafe { + sys::define_window( + start.x * 65536 + width, + start.y * 65536 + height, + params.color.as_rgb_val() + | (RELATIVE_FLAG | (params.title.is_some() as u32) << 4 | params.kind as u32) << 24, + params + .title + .map(|s| s.as_ptr()) + .unwrap_or_else(core::ptr::null) as u32, + ); + } } pub struct WindowTextParams<'a> { @@ -85,30 +72,23 @@ pub struct WindowTextParams<'a> { pub bg_color: Option, } -#[inline] -pub unsafe fn display_message(start: Dot, params: WindowTextParams<'_>) { +pub fn display_message(start: Dot, params: WindowTextParams<'_>) { const UTF8_FLAG: u32 = 0b0011_0000 << 24; const BG_FLAG: u32 = 0b0100_0000 << 24; - // XXX: llvm uses esi internally for x86-32 - // hope we're lucky enough so it won't be overwritten. - asm!("mov esi, {}", in(reg) params.text.len()); - syscall!( - 4, - in("ebx") start.x * 65536 + start.y, - in("ecx") params.color.as_rgb_val() | BG_FLAG * params.bg_color.is_some() as u32 | UTF8_FLAG, - in("edx") params.text.as_ptr() - ); -} -#[inline] -pub unsafe fn end_window_draw() { - syscall!(12, in("ebx") 2); + unsafe { + sys::display_message( + start.x * 65536 + start.y, + params.color.as_rgb_val() | BG_FLAG * params.bg_color.is_some() as u32 | UTF8_FLAG, + params.text.as_ptr() as u32, + 0, + params.text.len() as u32, + ); + } } pub fn exit() -> ! { - unsafe { syscall!(-1) }; - - unsafe { core::hint::unreachable_unchecked() } + unsafe { sys::exit() } } #[panic_handler] @@ -122,18 +102,16 @@ pub enum Event { KeyPress, } -#[inline] pub fn fetch_event() -> Option { - match unsafe { syscall!(10) } { + match unsafe { sys::wait_event() } { 1 => Some(Event::Redraw), 2 => Some(Event::KeyPress), _ => None, } } -#[inline] pub fn fetch_key() -> Option { - let res = unsafe { syscall!(2) }; + let res = unsafe { sys::pressed_key() }; if res == 1 { None } else { diff --git a/src/main.rs b/src/main.rs index 2f045cf..83a1e51 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,4 +1,3 @@ -#![feature(asm)] #![no_std] #![no_main] diff --git a/src/sys.rs b/src/sys.rs new file mode 100644 index 0000000..045df8f --- /dev/null +++ b/src/sys.rs @@ -0,0 +1,16 @@ +#[link(name = "syscalls")] +extern "C" { + pub fn start_window_draw(); + + pub fn end_window_draw(); + + #[link_name = "exit0"] + pub fn exit() -> !; + + pub fn define_window(ebx: u32, ecx: u32, edx: u32, edi: u32); + pub fn display_message(ebx: u32, ecx: u32, edx: u32, edi: u32, esi: u32); + + pub fn wait_event() -> u32; + + pub fn pressed_key() -> u32; +} diff --git a/src/syscalls.c b/src/syscalls.c new file mode 100644 index 0000000..81a6f86 --- /dev/null +++ b/src/syscalls.c @@ -0,0 +1,54 @@ +void start_window_draw() { + __asm__ volatile ( + "int $0x40;" + :: "a"(12), "b"(1) + ); +} + +void end_window_draw() { + __asm__ volatile ( + "int $0x40;" + :: "a"(12), "b"(2) + ); +} + +void exit0() { + __asm__ volatile ( + "int $0x40;" + :: "a"(-1) + ); +} + +void define_window(unsigned ebx, unsigned ecx, unsigned edx, unsigned edi) { + __asm__ volatile ( + "int $0x40;" + :: "a"(0), "b"(ebx), "c"(ecx), "d"(edx), "D"(edi) + : "memory" + ); +} + +void display_message(unsigned ebx, unsigned ecx, unsigned edx, unsigned edi, unsigned esi) { + __asm__ volatile ( + "int $0x40;" + :: "a"(4), "b"(ebx), "c"(ecx), "d"(edx), "D"(edi), "S"(esi) + : "memory" + ); +} + +unsigned wait_event() { + unsigned res; + __asm__ volatile ( + "int $0x40;" + : "=r"(res) : "a"(10) + ); + return res; +} + +unsigned pressed_key() { + unsigned res; + __asm__ volatile ( + "int $0x40;" + : "=r"(res) : "a"(2) + ); + return res; +} diff --git a/src/syscalls.o b/src/syscalls.o new file mode 100644 index 0000000000000000000000000000000000000000..bb7de80f645d8486195b69bf968b889e6f83af9c GIT binary patch literal 1336 zcmbtTJ4*vW5T1)~jUhe?L6KOgpo=L45s{PN3&cVYEDYh2oJLIU!re*|8#}=+KOz6a zMz9wA6LvOsb~=;WiJLW*4(!c*-#4=}+1=dj9__^}3)n2!h9AT%z((vRw%ef%aTtTs zgNL_ADtNJ**=I!WkCfR)u%F3nrk3`PPnT2av`C9JfPNHHxCU^c05Pzhh-0%9<{74y zVBMa8RZm*8@uA@+igU=*B1_O`Cy~65WyS{&F##cITg0RF(j(>fm-_a@$JcKKps&Zt z#4&MFSPsq5z?E0-38_c}2gLD+W#tT(8)LqqCw}=uovQ0GmiO z<~#d~uu+jt9z-aE$d@>hZe4;XI?@4=4?_?Izfy5M#4pDw3zFd+Qnc9m;NS5tI`L}oQr;|ZdnAhr&-@p zNoUHlGwVsG|E@+&%Bz-EquKXx^x+Alm_BHR0N~)^AAfTC| TJIn+|z3N|8;$