Use C for syscalls
This commit is contained in:
parent
aef1325ce9
commit
17ca59abe0
@ -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
8
build.rs
Normal 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");
|
||||
}
|
84
src/lib.rs
84
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<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 {
|
||||
|
@ -1,4 +1,3 @@
|
||||
#![feature(asm)]
|
||||
#![no_std]
|
||||
#![no_main]
|
||||
|
||||
|
16
src/sys.rs
Normal file
16
src/sys.rs
Normal 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
54
src/syscalls.c
Normal 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
BIN
src/syscalls.o
Normal file
Binary file not shown.
Loading…
Reference in New Issue
Block a user