作者:互联网 时间: 2026-09-11 10:10:01
准备试用carp之前,先别急着安装;这个项目提供的是C 语言中的“有趣”VM,看看这是如何进行的。这类日常自动化工具真正难在输入边界、依赖和失败处理如果不清楚就很难稳定复用,仓库说明只能作为第一层证据。落地前可以用一项范围明确的真实任务完成最小试跑,用配置时间、输出质量、异常信息和维护痕迹判断它是否真的省事。我的判断是,它更适合愿意先做小范围验证并复查原始文档的团队;若眼下没有这类需求,先保留观察即可。
THIS PROJECT IS UNSTABLE AND DEPRECATED
从那时起,我开始缓慢地致力于一个更稳定、更经过深思熟虑的项目 称为 RabbitVM。它并不完全具备 相同级别的文档,但它应该工作得更好。
CarpVM
这是我花了大约半年时间慢慢进行的一个项目。我的目标是尝试从头开始构建一个小型(且相当可靠)的 VM,同时学习越来越多的 C 语言。
现在有指令、寄存器、堆栈、数据存储器和调用。不确定递归是否有效......理论上应该如此。没有测试过。
CONSIDER THIS PRE-ALPHA SOFTWARE。事情的变化比 Rust 中的变化更多!
安装
获得鲤鱼
如果您已经有本地副本(在添加子模块之前克隆)
git fetchgit rebasegit submodule initgit submodule update如果您还没有本地副本
git clone --recursiveNOTE:如果 git submodule status 未返回 SHA1 哈希值和存储库名称,则表示有问题。
NOTE:递归克隆用于测试库。如果不包含在内,则不会构建测试。
建筑鲤鱼
makemake test(可选)make installmake clean(可选)测试机器
| 拱形(位) | OS(带版本、名称) | 编译器(带版本) |
|---|---|---|
| 64位 | Ubuntu 12.04(精确) | 海湾合作委员会4.6.3 |
| 64位 | Ubuntu 14.04(值得信赖) | 海湾合作委员会 4.8.2 |
| 32位 | Ubuntu 14.04(值得信赖) | 海湾合作委员会 4.8.2 |
| 64位 | OS X 10.9.4(小牛队) | 铿锵3.2 |
| 32位 | OS X 10.9.4(小牛队) | 海湾合作委员会4.2.1 |
| 64位 | Arch Linux 3.13.6-1 | 铿锵3.4.2 |
| 64 位? | Arch Linux 3.13.6-1 | 海湾合作委员会4.9.0 20140604 |
使用
NOTE:请参阅 carp -h 以获取有关命令行选项的帮助。
口译员
./carp.out -f your_file.carp。API
carp/carp_machine.h。gcc program.c /usr/local/lib/libcarp.a -o program.out。指令集
| 操作码 | 论点 | 描述 |
|---|---|---|
| HALT | 退出代码 | 将 ext 设置为给定代码,暂停并尝试清理堆栈、数据内存和标签内存。 |
| NOP | 什么都不做。严重地。 | |
| LOADR | 正则值 | 将给定的整数值加载到给定的寄存器中。 |
| LOAD | 差异 | 加载堆栈中位置 fp + diff 处的值。 |
| STORE | 差异,值 | 将值存储在位置 fp + diff 处。 |
| MOV | 目标、源 | 将 src 寄存器的内容复制到 dst 寄存器。 |
| ADD | 从堆栈中弹出顶部两个整数并压入它们的总和。 | |
| SUB | 从堆栈中弹出顶部的两个整数并压入差值(下限减去上限)。 | |
| MUL | 从堆栈中弹出前两个整数并压入它们的乘积。 | |
| MOD | 从堆栈中弹出顶部的两个整数并将 lower % 压入上层。 | |
| SHR | 从堆栈中弹出顶部的两个整数并压入 lower >> upper。 | |
| SHL | 从堆栈中弹出顶部的两个整数并压入 lower << upper。 | |
| NOT | 从堆栈中弹出顶部整数并按位压入该整数的 NOT。 | |
| XOR | 从堆栈中弹出顶部两个整数并按位压入 XOR.. | |
| OR | 从堆栈中弹出顶部两个整数并按位压入 OR。 | |
| AND | 从堆栈中弹出顶部两个整数并按位压入 AND。 | |
| INCR | 注册 | 增加给定寄存器中的值。 |
| DECR | 注册 | 减少给定寄存器中的值。 |
| INC | 增加堆栈顶部的值。 | |
| DEC | 递减堆栈顶部的值。 | |
| PUSHR | 注册 | 将值推入给定寄存器。 |
| PUSH | 瓦尔 | 推动给定值。 |
| POP | 注册 | 从堆栈中弹出一个整数并将其转储到给定的寄存器中。 |
| CMP | 从堆栈中弹出顶部两个整数并检查是否相等。 0表示相等。推动结果。 | |
| LT | 从堆栈中弹出顶部的两个整数并检查是否 lower < upper。推动结果。 | |
| GT | 从堆栈中弹出顶部的两个整数并检查是否 lower > upper。推动结果。 | |
| JZ | 地址 | 如果栈顶为 0,则跳转到给定的绝对地址。 |
| RJZ | 差异 | 如果堆栈顶部为 0,则将差分添加到 ip(相对跳转)。 |
| JNZ | 地址 | 如果栈顶不为 0,则跳转到给定的绝对地址。 |
| RJNZ | 差异 | 如果堆栈顶部不为 0,则将差分添加到 ip(相对跳转)。 |
| JMP | 地址 | 无条件跳转到给定的绝对地址。 |
| RJMP | 差异 | 无条件向ip(相对跳转)添加微分。 |
| CALL | key/addr | 保存状态并将 IP 设置为按键数据存储器中的值。函数可能返回 ax 中的值。 |
| RET | 将堆栈顶部放入 ax 并加载之前的状态。 |
|
| PREG | 注册 | 打印给定寄存器的内容。 |
| PTOP | 查看堆栈顶部并打印顶部值。 |
寄存器
| 名称 | 目的 |
|---|---|
r0 ... r9 |
通用用途。 |
ax |
用户定义函数的返回值。 |
bx, cx, dx, rx |
......未来的事情。暂时只占空间。 |
ip |
指令指针。用于在代码、goto、调用等中保留位置。 |
sp |
堆栈指针。 |
fp |
帧指针。用于保存函数调用的状态。 |
gbg |
垃圾寄存器主要用于弹出。 |
run |
布尔值 - 机器正在运行吗? |
ext |
退出代码。 |