9 个版本
0.2.0 | 2024 年 3 月 2 日 |
---|---|
0.1.7 | 2023 年 9 月 18 日 |
0.1.4 | 2023 年 8 月 19 日 |
#41 in 模拟器
用于 ssemu
130KB
1.5K SLoC
曼彻斯特小型实验机器 "婴儿" 仿真库
此库提供了一组类型和方法,用于仿真和汇编 曼彻斯特婴儿 的代码,这是第一台存储程序的计算机。
说明
曼彻斯特 "婴儿" 是第一个将程序代码和数据存储在公共随机访问内存中的计算机,因此它被认为是第一个运行 "真正" 软件的机器,为熟悉汇编的任何人提供了一个熟悉的(尽管是原始的)编程环境,此库可以包含在各种软件和平台上,以便仿真此历史机器的功能。
此库提供了一个将婴儿作为字节码解释器(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());
}