1
0
forked from Rust/Core

Use C for syscalls

This commit is contained in:
Kitsu 2021-12-09 02:18:30 +03:00
parent aef1325ce9
commit 17ca59abe0
7 changed files with 112 additions and 54 deletions

View File

@ -12,3 +12,6 @@ lto = "thin"
[dependencies]
cstr_core = { version = "0.2.4", default-features = false, features = ["nightly"] }
[build-dependencies]
cc = "1.0.72"

8
build.rs Normal file
View File

@ -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");
}

View File

@ -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<Color>,
}
#[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<Event> {
match unsafe { syscall!(10) } {
match unsafe { sys::wait_event() } {
1 => Some(Event::Redraw),
2 => Some(Event::KeyPress),
_ => None,
}
}
#[inline]
pub fn fetch_key() -> Option<u8> {
let res = unsafe { syscall!(2) };
let res = unsafe { sys::pressed_key() };
if res == 1 {
None
} else {

View File

@ -1,4 +1,3 @@
#![feature(asm)]
#![no_std]
#![no_main]

16
src/sys.rs Normal file
View File

@ -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;
}

54
src/syscalls.c Normal file
View File

@ -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;
}

BIN
src/syscalls.o Normal file

Binary file not shown.