MiniASM —— 一个类 RISC 汇编虚拟机 用 Rust 从零实现的汇编器与虚拟机。包含两趟扫描汇编器、基于寄存器的执行引擎,以及完整的指令集。
两趟扫描汇编器 :支持标签(label)、自动地址解析、语法检查类 RISC 指令集 :30 条指令,三地址格式,操作清晰寄存器架构 :11 个通用寄存器(R0–R10),R0 恒零,R10 兼作栈指针内存与栈 :1024 单元内存,栈向高地址生长函数调用 :CALL / RET + 硬件栈,支持子程序条件跳转 :基于零标志(Z)和符号标志(S)的 7 种跳转I/O 支持 :整数输出 PRINT 与 ASCII 字符输出 PRINTCgit clone https://github.com/0x8000S/MiniASM.git
cd MiniASM
cargo run 默认会执行 main.rs 中嵌入的测试程序。你也可以修改 main() 里的 code 字符串来运行自己的汇编代码。
指令 格式 说明 MOVMOV dst, srcsrc 可以是寄存器或立即数
指令 格式 说明 ADDADD dst, a, bdst = a + bSUBSUB dst, a, bdst = a - bMULMUL dst, a, bdst = a * bDIVDIV dst, a, bdst = a / b(整除,除零报错)MODMOD dst, a, bdst = a % bANDAND dst, a, b按位与 OROR dst, a, b按位或 XORXOR dst, a, b按位异或 SHLSHL dst, a, bdst = a << bSHRSHR dst, a, bdst = a >> b
指令 格式 说明 CMPCMP a, b比较 a 和 b,更新 Z/S 标志 NEGNEG dst, srcdst = -srcNOTNOT dst, srcdst = !src(按位取反)INCINC rr += 1DECDEC rr -= 1
指令 条件 JMP无条件 JE相等(Z = true) JNE不等(Z = false) JG大于(Z = false 且 S = false) JL小于(S = true) JGE大于等于(S = false) JLE小于等于(Z = true 或 S = true)
指令 格式 说明 PUSHPUSH r将寄存器值压栈 POPPOP r弹栈到寄存器 CALLCALL label调用子程序 RETRET返回
指令 格式 说明 LOADLOAD r, [addr]r = memory[addr_reg]STORESTORE [addr], rmemory[addr_reg] = r
指令 格式 说明 PRINTPRINT r以整数形式输出,带换行 PRINTCPRINTC r以 ASCII 字符形式输出,不换行 HALTHALT停机
_start: MOV R1 , 0 ; sum = 0 MOV R2 , 1 ; i = 1 MOV R3 , 10 ; max = 10 loop : CMP R2 , R3 JG done ADD R1 , R1 , R2 ; sum += i MOV R4 , 1 ADD R2 , R2 , R4 ; i += 1 JMP loop done: PRINT R1 ; 输出 55 HALT _start: MOV R1 , 7 CALL double PRINT R1 ; 输出 14 HALT double: MOV R2 , 2 MUL R1 , R1 , R2 RET _start: MOV R1 , 100 ; 地址 MOV R2 , 42 STORE [ R1 ], R2 ; memory[100] = 42 LOAD R3 , [ R1 ] ; R3 = memory[100] PRINT R3 ; 输出 42 HALT 汇编源码
│
▼
[汇编器] ──→ 第一趟:收集标签地址
│ ──→ 第二趟:生成指令序列
▼
指令序列 (Vec<Inst>) + 入口地址
│
▼
[虚拟机] ──→ Fetch → Decode → Execute 循环
│
▼
执行结果
寄存器 :R0(恒零)、R1–R9(通用)、R10(SP)内存 :1024 个 i64 单元,栈与数据区共享标志位 :Z(零标志)、S(符号标志)标签必须独占一行 ,以冒号结尾,例如 loop:。 程序入口为 _start: 标签;若不存在,默认从第 0 条指令开始。 算术指令(ADD/SUB 等)的源操作数只能是寄存器 ,立即数需先用 MOV 载入。 注释以分号 ; 开头。