9 个版本

0.2.0 2024 年 3 月 2 日
0.1.7 2023 年 9 月 18 日
0.1.4 2023 年 8 月 19 日

#41 in 模拟器


用于 ssemu

MIT 许可证

130KB
1.5K SLoC

曼彻斯特小型实验机器 "婴儿" 仿真库

crates.io Released API docs MIT licensed

此库提供了一组类型和方法,用于仿真和汇编 曼彻斯特婴儿 的代码,这是第一台存储程序的计算机。

说明

曼彻斯特 "婴儿" 是第一个将程序代码和数据存储在公共随机访问内存中的计算机,因此它被认为是第一个运行 "真正" 软件的机器,为熟悉汇编的任何人提供了一个熟悉的(尽管是原始的)编程环境,此库可以包含在各种软件和平台上,以便仿真此历史机器的功能。

此库提供了一个将婴儿作为字节码解释器(baby_emulator::core::BabyModel)进行仿真的接口,以及一个用于将汇编语言(使用现代和原始汇编语言符号)汇编成仿真器可以运行的格式的库(baby_emulator::assembler)。

请将任何问题或问题记录在 GitHub 仓库 上。

安装

命令行

cargo add baby-emulator 

Cargo.toml

baby-emulator = "0.2.0" 

示例

这显示了此库的一些简短示例,旨在作为起点,允许 "用户" 进一步进行实验。有关更多信息,请参阅 文档

字节码解释器仿真

此库的核心是 baby_emulator::core::BabyModel 结构,该结构具有表示婴儿所有内部寄存器和 32 个单词内存的字段,您可以使用一个包含 [i32; 32] 的数组初始化此结构,该数组可以包含从位置 0 开始的程序代码指令。

此示例运行一个示例程序,该程序将5加5并将结果存储在累加器中。在这里的运行是通过run_loop方法完成的,该方法将简单地执行连续的指令,直到抛出错误(如停止指令)或者迭代次数超过指定的限制。

use baby_emulator::core::BabyModel;
use baby_emulator::core::errors::BabyErrors;
use baby_emulator::core::errors::BabyError;

let model = BabyModel::new_example_program();
match model.run_loop(100) {
    (model, BabyErrors::Stop(_)) => println!("{}", model.core_dump()),
    (_, err) => println!("{}", err.get_descriptor())
}

您还可以逐条执行仿真,使用execute方法一次执行一条指令,并查看直接结果。

use baby_emulator::core::BabyModel;
use baby_emulator::core::errors::BabyError;

let model = BabyModel::new_example_program();
match model.execute() {
    Ok(m) => println!("{}", m.core_dump()),
    Err(e) => println!("Error {}", e.get_descriptor())
}

汇编

这里是一个使用现代符号汇编Baby asm字符串的示例,然后运行结果程序;有关更多信息,请参阅baby_emulator::assembler文档。

use baby_emulator::assembler::assemble; 
use baby_emulator::core::{BabyModel, instructions::BabyInstruction};
 
 
const ASM: &str = 
"
ldn $start_value  ; Loads 10 into the accumulator 

:loop_start_value ; The memory address the loop should return to 
sub $subtract_val ; Subtract 1 from the accumulator 
cmp               ; Skip the next jump instruction if the accumulator is negative 
jmp $loop_start   ; Jump to the start of the loop 
stp               ; Program stops when the accumulator is negative 

:loop_start       ; Pointer to the memory address the loop should return to 
abs $loop_start_value

:subtract_val     ; Value to be subtracted
abs 0d1

:start_value      ; Value to start in the accumulator 
abs 0d-10
";

fn main() {
    let instructions = match assemble(&String::from(ASM), false) {
        Ok(v) => v,
        Err(e) => { println!("{}", e.describe(true)); return; }
    };
    let main_store = BabyInstruction::to_numbers(instructions);
 
    let mut model = BabyModel::new_with_program(main_store);
    loop {
        model = match model.execute() {
            Ok(m) => m,
            Err(_) => break
        };
    }
    println!("{}", model.core_dump());
}

无运行时依赖