Skip to content

Latest commit

 

History

History
180 lines (121 loc) · 4.7 KB

19271169-张东植-实验报告1.md

File metadata and controls

180 lines (121 loc) · 4.7 KB

19271169-张东植-实验报告1

[TOC]

1. 创建Rust项目

  1. New a Rust project with the following commands.

    root@iZuf6hkk04t6lezxufufk6Z:~# cd os
  2. Build the created Rust project.

    root@iZuf6hkk04t6lezxufufk6Z:~# cargo build
  3. Run the Rust project.

    root@iZuf6hkk04t6lezxufufk6Z:~# cargo run

    image-20211112105842046

2. 移除标准库依赖

​ remove the dependencies of standard libs.

2.1 修改target

​ Modify target to riscv64. Add build config to the configuration file.

image-20211112114031900

2.2 修改main.rs

​ Modify file "main.rs". Delete main function and add some codes.

// main.rs
use core::panic::PanicInfo;

#[panic_handler]
fn panic(_info: &PanicInfo) -> ! {
    loop {}
}

image-20211112110921023

2.3 分析独立可执行程序

​ In the end, analyze the independent executable program.

​ We can find out that the binary generated by the compilation was found to be an empty program because the compiler could not find the entry function, so no subsequent code was generated.

root@iZuf6hkk04t6lezxufufk6Z:~# file target/riscv64gc-unknown-none-elf/debug/os
root@iZuf6hkk04t6lezxufufk6Z:~# rust-readobj -h target/riscv64gc-unknown-none-elf/debug/os
root@iZuf6hkk04t6lezxufufk6Z:~# rust-objdump -S target/riscv64gc-unknown-none-elf/debug/os

image-20211112111646398

3. 用户态可执行的环境

3.1 增加入口函数

​ Add the following codes to "main.rs". Then run the program.

​ A Segmentation fault occurs. This is because the program currently lacks a proper exit mechanism.

#[no_mangle]
extern "C" fn _start() {
    loop{};
}

image-20211112111750688

image-20211112111936617

3.2 实现退出机制

​ To implement the exit mechanism, we need to add the following codes to "main.rs".

#![feature(asm)]

const SYSCALL_EXIT: usize = 93;

fn syscall(id: usize, args: [usize; 3]) -> isize {
    let mut ret: isize;
    unsafe {
        asm!("ecall",
             in("x10") args[0],
             in("x11") args[1],
             in("x12") args[2],
             in("x17") id,
             lateout("x10") ret
        );
    }
    ret
}

pub fn sys_exit(xstate: i32) -> isize {
    syscall(SYSCALL_EXIT, [xstate as usize, 0, 0])
}

#[no_mangle]
extern "C" fn _start() {
    sys_exit(9);
}

image-20211112112819594

3.3 实现输出支持

  1. First, encapsulate the SYSCALL_WRITE system call. This is a system call provided by the Linux operating system kernel with the ID SYSCALL_WRITE.

    const SYSCALL_WRITE: usize = 64;
    
    pub fn sys_write(fd: usize, buffer: &[u8]) -> isize {
      syscall(SYSCALL_WRITE, [fd, buffer.as_ptr() as usize, buffer.len()])
    }
  2. Then, implement the data structure based on Write Trait, complete the write_str function required for Write Trait, and wrap it with the print function.

    struct Stdout;
    
    impl Write for Stdout {
        fn write_str(&mut self, s: &str) -> fmt::Result {
            sys_write(1, s.as_bytes());
            Ok(())
        }
    }
    
    pub fn print(args: fmt::Arguments) {
        Stdout.write_fmt(args).unwrap();
    }
  3. Finally, implement Rust language formatting macros based on print function.

    use core::fmt::{self, Write};
    
    #[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)+)?) => {
            print(format_args!(concat!($fmt, "\n") $(, $($arg)+)?));
        }
    }

image-20211112113544745

image-20211112113600224

image-20211112114206117

image-20211113115600270