OS 简单教程三OS 简单教程三
🕋

OS 简单教程三

打印

继续打印,幸好 SBI 实现了打印,省去了自己实现驱动,调用系统调用就行了。
实现系统调用,在 scall_sbi/mod.rs 中
#[inline(always)] fn scall(which: usize, arg0: usize, arg1: usize, arg2: usize) -> usize {    let mut ret;    unsafe {        asm!("ecall",            in( "x10") arg0,            in("x11") arg1,            in ("x12") arg2,            in("x17") which,            lateout("x10") ret,            options(nostack)       );   }    ret } const SBI_CONSOLE_PUTCHAR: usize = 1; const SBI_SHUTDOWN: usize = 8; pub fn shutdown() -> ! {    scall(SBI_SHUTDOWN, 0, 0, 0);    panic!("It should shutdown!"); } pub fn put_char(c: usize) {    scall(SBI_CONSOLE_PUTCHAR, c, 0, 0); }
建立 console.rs 调用刚才的系统调用,内容是
use core::fmt::{self, Write}; use crate::scall_sbi::put_char; struct STDOUT; impl Write for STDOUT {    fn write_str(&mut self, s: &str) -> core::fmt::Result {        for c in s.chars() {            put_char(c as usize);       }        Ok(())   } } pub fn print(args: fmt::Arguments){    STDOUT.write_fmt(args).unwrap(); } #[macro_export] macro_rules! print {   ($fmt: literal $(, $($arg: tt)+)?) => {       $crate::console::print(format_args!($fmt $(, $($arg)+)?));   } } #[macro_export] macro_rules! println {   ($fmt: literal $(, $($arg: tt)+)?) => {       $crate::console::print(format_args!(concat!($fmt, "\n") $(, $($arg)+)?));   } }
说明一下
  • 利用 宏 + core::fmt::Write 来解析参数
main.rs 里就可以调用宏输出了,这时 main.rs 的内容
#![feature(llvm_asm)] #![feature(global_asm)] #![no_std] #![no_main] use scall_sbi::shutdown; mod lang; mod scall_sbi; #[macro_use] mod console; global_asm!(include_str!("stack.asm")); #[no_mangle] extern "C" fn rust_main() ->! {    println!("hello OS");    shutdown(); }
编译一下,make build,编译过了,运行一下 make run 也成功了,输出
[rustsbi] RustSBI version 0.2.0-alpha.3 .______       __   __     _______.___________. _______..______   __ |   _ \     | | | |   /       |           | /       ||   _ \ | | | |_) |   | | | |   |   (----`---| |----`|   (----`| |_) || | |     /     | | | |   \   \       | |     \   \   |   _ < | | | |\ \----.| `--' |.----)   |     | | .----)   |   | |_) || | | _| `._____| \______/ |_______/       |__| |_______/   |______/ |__| [rustsbi] Platform: K210 (Version 0.2.0) [rustsbi] misa: RV64ACDFIMSU [rustsbi] mideleg: 0x22 [rustsbi] medeleg: 0x1ab [rustsbi] Kernel entry: 0x80020000 hello OS [rustsbi] reset triggered! todo: shutdown all harts on k210; program halt. Type: 0, reason: 0
至此我们成功准备了运行环境并在 k210 上输出,接下来我们开始虚拟化 CPU 和内存,这更有趣!

后续

  • 全局位初始化变量清零
fn clear_bss() {    extern "C" {        fn sbss();        fn ebss();   }   (sbss as usize..ebss as usize).for_each(|a| {        unsafe { (a as *mut u8).write_volatile(0) }   }); }
具体代码请参考 https://github.com/buhe/bugu/tree/0.1.0