在Rust 中, 我們都習慣用 writeln! write! panic! 等等的macro 作為字串流的後處理

那麼, 在no_std 中, 也是可以享用這些Rust 的特性的。

vga_buffer.rs 中加入

use core::fmt; //建議放第一行

impl fmt::Write for Writer {
    fn write_str(&mut self, s: &str) -> fmt::Result {
        self.write_string(s);
        Ok(())
    }
}

print_something() 改寫成 :

pub fn print_something() {
    use core::fmt::Write;
    let mut writer = Writer {
        column_position: 0,
        color_code: ColorCode::new(Color::Yellow, Color::Black),
        buffer: unsafe { &mut *(0xb8000 as *mut Buffer) },
    };

    writer.write_byte(b'H');
    writer.write_string("ello! ");
    write!(writer, "The numbers are {} and {}", 42, 1.0/3.0).unwrap();
}

然而這次我們再打開, 就發現... QEMU 不斷重啟了...

如果出現這個情況, 可能是你的 json 檔案寫錯了。檢查一下 , 修好之後要記得先 cargo clean 到現在為止, build 和xbuild 都不能按照這個檔案自動刪除舊緩存。

小插曲, 為了減少一個warning, 我把項目中的aCore 改名為 a_core 你可以修改Cargo.toml, 設 name = "a_core" 。 然後 , 運行方法以後改成 qemu-system-x86_64 -drive format=raw,file=target/x86_64-aCore/debug/bootimage-a_core.bin

Newlines

回到Writer 把Newline 完成

先寫一個叫 clear_row 的function

impl Writer {
    fn new_line(&mut self) {
        for row in 1..BUFFER_HEIGHT {
            for col in 0..BUFFER_WIDTH {
                let character = self.buffer.chars[row][col].read();
                self.buffer.chars[row - 1][col].write(character);
            }
        }
        self.clear_row(BUFFER_HEIGHT - 1);
        self.column_position = 0;
    }

    fn clear_row(&mut self, row: usize) {
        let blank = ScreenChar {
            ascii_character: b' ',
            color_code: self.color_code,
        };
        for col in 0..BUFFER_WIDTH {
            self.buffer.chars[row][col].write(blank);
        }
    }
}

原理是 : 把每一格文字都移上一列, 然後把最下面的一行清空。 清空時我們用一個 clear_row , 方法是在每一格寫入 b''

結果如上