【免费下载链接】xquad
A rust implementation of the Quip Network's quantum virtual machine.
本文是 XQuad 工具链统一命令行xqcli(构建产物为xquad二进制)的完整技术指南。它覆盖安装方式、asm/dism/run/verify四个子命令的全部参数与用法,并结合仓库源码说明每条命令背后的调用链(xqasm 汇编 → xqvm 字节码编码 → 解释执行 → 全相位验证)与默认值来源。读完本文,你可以熟练地完成"编写 .xqasm → 汇编成 .xqb → 校验 → 运行 → 反汇编"的完整工作流,并能理解每一步在代码中的具体实现位置。
项目背景:为什么 crate 叫xqcli,命令却叫xquad
xqcli是 XQuad 工具链(一个 Rust 实现的量子虚拟机项目,见仓库根目录 README.md)的统一命令行入口。这里有一个容易踩的坑:crate 名为xqcli,但它构建出来的二进制叫xquad。在 xqcli/Cargo.toml 中可以看到明确的声明:
[package] name = "xqcli" description = "Unified CLI for the XQuad Toolchain" [[bin]] name = "xquad" path = "src/main.rs"因此执行cargo install xqcli之后,安装的命令是xquad而不是xqcli;运行xqcli --help会因不存在该二进制而失败。这一点在 xqcli/README.md 开头被专门强调。
从 xqcli/src/main.rs 的源码可以看到,CLI 使用clap解析,顶层结构非常简单:一个Command枚举承载四个子命令,main()中按子命令分发到对应模块执行:
enum Command { Asm(asm::Args), Dism(dism::Args), Run(run::Args), Verify(verify::Args), }安装
通过 crates.io 直接安装:
cargo install xqcli xquad --help安装后执行xquad --help会显示四个子命令的概要,xquad <subcommand> --help可查看每个子命令的完整选项列表。仓库采用 Rust 2024 edition,依赖xqasm、xqvm(workspace 内部 crate)、clap与miette(错误诊断),详见 xqcli/Cargo.toml;从源码构建可基于仓库根目录的 workspace 执行cargo build。
子命令总览:一条命令对应工具链的一个阶段
xquad的四个子命令与工具链阶段一一对应,在 xqcli/src/main.rs 的注释中有明确表述:
| 子命令 | 作用 | 核心实现文件 |
|---|---|---|
xquad asm <INPUT> | 将.xqasm汇编源码装配为.xqb字节码 | xqcli/src/asm.rs |
xquad dism [FILE] | 将字节码反汇编为人类可读的指令清单 | xqcli/src/dism.rs |
xquad run <FILE> | 在解释器上运行字节码(配合--text可运行汇编) | xqcli/src/run.rs |
xquad verify <FILE> | 运行字节码验证器(全部相位) | xqcli/src/verify.rs |
四个子命令的常用参数速览(完整参数请用xquad <subcommand> --help查看):
xquad asm:-o, --output <OUTPUT>指定输出文件(默认<输入文件名>.xqb);--stdout将字节码写到标准输出而不是文件(与-o互斥,见 xqcli/src/asm.rs 中的conflicts_with声明)。xquad dism:省略FILE时从标准输入读取字节码。xquad run:--text将FILE视为汇编源码;--calldata <CALLDATA>传逗号分隔的整型 calldata;--outputs <OUTPUTS>设置输出槽数量(默认 16);--step-limit <STEP_LIMIT>设置精确步数上限(默认 10000000,值为 0 时不执行任何指令);--unlimited-steps移除步数上限;--memory-limit设置内存分配预算(默认 1073741824 字节,即 1 GiB);--trace开启逐步执行追踪,配合--trace-format text|json与--trace-file <FILE>使用。xquad verify:--text将FILE视为汇编源码、先汇编再验证。
xquad asm:把 XQASM 源码汇编成字节码
asm子命令的完整流程在 xqcli/src/asm.rs 中:
- 读取输入源文件;
- 调用
xqasm::parse将源码解析为指令行(xqasm/src/lib.rs 中定义,每条源行可包含;注释、name:标签定义与MNEMONIC [operands...]指令,操作数支持r0~r255寄存器、42/-99/0xFF整型字面量与标签引用); - 调用
xqasm::assemble生成xqvm::Program; - 调用
program.encode()得到二进制字节码; - 按
--stdout或-o/--output(默认<input>.xqb)输出。
输出到文件时,asm还会向 stderr 打印一行摘要:assembled <指令数> instructions (<字节数> bytes) -> <输出路径>,其中指令数通过xqvm::InstructionStream逐条解码统计得到。
典型用法:
# 默认输出到 add.xqb xquad asm add.xqasm # 指定输出文件 xquad asm add.xqasm -o out/add.bin # 字节码直接写到 stdout(可用于管道,如 xquad asm a.xqasm --stdout | xquad run --file -) xquad asm add.xqasm --stdout在 xqcli/tests/cli.rs 中,asm_writes_default_xqb_file、asm_custom_output_path、asm_stdout_flag_emits_nonempty_bytes分别验证了默认输出路径、自定义输出路径与--stdout行为;asm_invalid_source_exits_nonzero验证非法源码(如NOTANOPCODE)时进程以非零状态退出。
xquad dism:把字节码反汇编成可读清单
dism子命令在 xqcli/src/dism.rs 中实现:读取FILE(省略时从 stdin 读取全部字节),调用xqvm::Program::decode解码字节码,再通过xqvm::disasm::Disassembly::from_program生成反汇编文本输出到 stdout。
一个值得注意的细节:反汇编清单中跳转目标会以.0、.1……的形式打上标签,这些标签来自字节码的 jump table(见 xqcli/src/dism.rs 顶部注释)。因此含跳转的程序反汇编后比原始汇编多出.N:形式的跳转标签行。
用法:
xquad dism add.xqb # 反汇编文件 xquad dism < add.xqb # 从 stdin 读取 xquad asm add.xqasm --stdout | xquad dism # 汇编结果直接反汇编测试dism_file_listing_contains_push验证反汇编输出包含PUSH指令,dism_reads_stdin_when_no_file验证省略FILE时从 stdin 读取。
xquad run:解释执行字节码或汇编
run子命令是四个子命令中最复杂的一个,参数与默认值在 xqcli/src/run.rs 中定义。执行流程为:
- 读取
FILE字节;若指定--text,则先按 UTF-8 校验并调用xqasm::assemble_source(xqasm/src/lib.rs 提供的 parse + assemble 一步入口)就地汇编;否则调用xqvm::Program::decode解码字节码; - 构造
xqvm::Vm,通过链式调用set_calldata(...)、set_output_slots(...)、set_step_limit(...)/set_unlimited_steps()、set_memory_limit(...)配置虚拟机; - 根据是否启用
--trace,调用vm.run(&program)或vm.run_trace(&mut tracer, &program)执行; - 执行结束后打印输出槽(
outputs:,格式为[i] = value,跳过未设置的槽)与剩余栈(stack (bottom to top):,自底向上逐值打印),见print_results函数。
关键参数详解
--text:把输入当作文本汇编而非二进制字节码。run与verify都支持,适合快速试跑一段源码而无需先生成.xqb。--calldata <CALLDATA>:逗号分隔的整型列表,作为INPUT指令读取的 calldata。源码中通过value_delimiter = ','让 clap 直接按逗号切分,再映射为RegVal::Int。测试run_calldata_reaches_input_instruction验证了--calldata 99能被程序中的INPUT r0读到。--outputs <OUTPUTS>:OUTPUT指令可用的输出槽数量,默认 16。--step-limit <STEP_LIMIT>:最大可执行指令数,默认值 10000000。该值是一个精确上限而非哨兵值:--step-limit 0表示真正的零预算,任何程序的第一条指令都会被拒绝执行(见测试run_step_limit_zero_exits_nonzero的注释:"0 = unlimited 会让最安全的取值变成最危险的取值")。默认值来源于xqvm::vm::DEFAULT_STEP_LIMIT,定义于 xqvm/src/vm.rs:
pub const DEFAULT_STEP_LIMIT: u64 = 10_000_000;该常量之所以设为公开,是因为xqcli run的默认值、Python VM 包装器、conformance 测试框架与xqvm本身四方都必须对齐同一个步数上限,公开常量可防止各方各自抄写字面量而漂移。
--unlimited-steps:移除步数上限。它与--step-limit通过conflicts_with互斥——放弃上限必须显式说出来,同时说两种方式会被 clap 判为用法错误(退出码 2)而非由 VM 做优先级裁决(见测试run_step_limit_and_unlimited_steps_conflict)。注意:不 halt 的程序在无限步数下不会返回。测试run_unlimited_steps_removes_the_bound用一百万次迭代的循环验证该标志确实移除了默认上限。--memory-limit:模型、样本与向量的内存分配预算,默认 1073741824(1 GiB)。该默认值对应 xqvm/src/vm.rs 的DEFAULT_MEMORY_LIMIT: u64 = 1 << 30;注释说明 1 GiB 预算足以容纳 1.34 亿变量的样本,远超当前工具链可编译的程序规模,同时又限制了恶意程序向宿主索要的内存,嵌入方(尤其 Substrate pallet)应设置更小的预算。--trace:开启逐步执行追踪,输出每一执行的 step 号、字节偏移、指令、栈、读写的寄存器。默认写到 stderr。--trace-format text|json:text为对齐列的人类可读格式(xqvm/src/tracer/text.rs 中实现,栈最多显示 8 个元素、超出截断为[...N more, top...]);json为每行一个 JSON 对象的 JSONL 格式(xqvm/src/tracer/json.rs 中手写序列化,字段为step、pos、instruction、stack、read_regs、written_regs)。该参数要求--trace已启用(claprequires)。--trace-file <FILE>:把追踪输出写到文件而不是 stderr,同样要求--trace。
追踪的完整示例(写入文件便于事后分析):
xquad run add.xqasm --text --trace --trace-format json --trace-file trace.jsonl测试run_trace_produces_stderr_output、run_trace_json_format_emits_json_objects、run_trace_file_creates_nonempty_file分别覆盖了追踪的 stderr 输出、JSON 格式与写文件行为。
xquad verify:运行全相位字节码验证器
verify子命令在 xqcli/src/verify.rs 中实现:读取FILE(默认按字节码处理,--text时先汇编),调用xqvm::verifier::verify(&program)(xqvm/src/verifier/mod.rs 中的Verifier::default().run(program)),通过后打印ok: <文件> (<N> instruction[s])并以状态 0 退出;遇到第一个违规即返回错误并以状态 1 退出。
verify覆盖的检查相位(见 xqvm/src/verifier/mod.rs 的相位表):
| 相位 | 检查内容 | 典型错误 |
|---|---|---|
StructuralPhase | 字节截断、未知操作码 | TruncatedInstruction、BadOpcode |
JumpTargetPhase | 跳转标签是否越界 | UndefinedJumpTarget |
LoopNestingPhase | 循环开/关括号配对、循环上下文读取 | NoActiveLoop、UnmatchedLoop |
RegisterTypePhase | 基于 CFG 的"未写先读"与类型状态不匹配 | ReadUnsetRegister、RegisterTypeMismatch |
UninitRegisterPhase | CFG AND-meet:至少一条路径上寄存器未初始化 | ReadUnsetRegister |
StackDepthPhase | 基于 CFG 的栈深度:下溢/上溢、循环平衡、汇合点深度不一致 | StackUnderflow、StackOverflowRisk、LoopStackImbalance、StackDepthMismatch |
其中结构性、跳转目标、循环嵌套三个相位合并为一个组合扫描 pass(scan),其余相位各自构建控制流图并运行前向 worklist 分析。这保证了进入 VM 执行的字节码在结构上自洽、寄存器读写合法、栈深度平衡——这正是"先 verify 再 run"的最佳实践依据。
快速上手:完整的四步工作流
以 xqcli/README.md 中的加法程序为例,从汇编到运行、反汇编、验证一气呵成:
cat > add.xqasm <<'EOF' ; add.xqasm -- push two integers and add them PUSH 10 PUSH 32 ADD HALT EOF xquad asm add.xqasm -o add.xqb xquad run add.xqb xquad dism add.xqb xquad verify add.xqbxquad run add.xqb的输出(剩余栈,自底向上):
stack (bottom to top): 42如果使用--text模式,可以跳过汇编步骤直接试跑:
xquad run add.xqasm --text用--calldata传入外部数据、用--outputs收集OUTPUT指令的结果:
cat > echo.xqasm <<'EOF' ; echo.xqasm -- read calldata[0], push it, output it, halt PUSH 0 INPUT r0 LOAD r0 OUTPUT 0 HALT EOF xquad run echo.xqasm --text --calldata 99 --outputs 4源码级调用链:一条命令如何串起整个工具链
从 xqcli/src/main.rs 的分发逻辑出发,可以梳理出四个子命令各自依赖的底层 crate 能力,这正是xqcli被称为"统一 CLI"的原因——它本身几乎不含业务逻辑,只是把 XQuad 工具链的库能力暴露成命令行:
- 汇编路径:
xqasm::parse→xqasm::assemble→xqvm::Program::encode(xqcli/src/asm.rs)。汇编器是文本格式(.xqasm)与二进制格式(.xqb)之间的唯一桥梁,其语法约定详见 xqasm/src/lib.rs 与仓库根目录的 xqasm/README.md。 - 解码路径:
xqvm::Program::decode→xqvm::disasm::Disassembly(xqcli/src/dism.rs)。字节码编码格式的规范说明见 spec/xqvm/ENCODING.md。 - 执行路径:
xqvm::Vm的run/run_trace,配合xqvm的TextTracer/JsonTracer追踪器(xqcli/src/run.rs)。VM 的指令语义、寄存器与值模型参见 xqvm/README.md 与 spec/xqvm/SPEC.md。 - 验证路径:
xqvm::verifier::verify,即Verifier::default().run(program)(xqcli/src/verify.rs)。
仓库还提供了同一工具链的 Python 侧实现(xqvm_py/ 的 executor、opcodes、tracer 等模块)以及 conformance 测试向量(conformance/vectors/ 下的.xqasm+inputs.json+expected.json三元组),它们与xqcli共享同一套 spec/xqvm/SPEC.md 语义,可作为理解指令行为的补充材料。
许可证
xqcli以 AGPL-3.0-or-later 许可证发布(见 xqcli/Cargo.toml 的license.workspace与各源码文件头部声明)。
小结
xqcli以极薄的一层 CLI 封装,把 XQuad 工具链的"汇编—反汇编—执行—验证"四个阶段串成了四个子命令。理解crate 名 xqcli / 二进制名 xquad的差异、--step-limit的精确上限语义、--unlimited-steps与--step-limit的互斥关系、--trace系列参数的依赖约束,以及verify背后的六类检查相位,是高效使用该工具的关键;这些行为在 xqcli/tests/cli.rs 中均有对应的集成测试可查证。
【免费下载链接】xquad
A rust implementation of the Quip Network's quantum virtual machine.
相关推荐
CubeFS blobstore-cli 命令行工具使用指南:配置、命令与源码解析
CubeFS blobstore cli 命令行工具使用指南:配置、命令与源码解析 本篇指南围绕 CubeFS 纠删码(blobstore)子系统的运维调试命令
存储分布式文件系统对象存储云原生NSwag工具链实战:命令行与GUI工具使用
NSwag工具链实战:命令行与GUI工具使用 本文深入探讨NSwag工具链的核心组件和使用方法,涵盖命令行工具、NSwagStudio图形界面、MSBuild集
开发工具代码生成API设计Airtest 命令行工具(airtest.cli)全解析:run、info、report 子命令与源码级执行原理
Airtest 命令行工具(airtest.cli)全解析:run、info、report 子命令与源码级执行原理 Airtest 是跨平台(Android /
测试质量保障计算机视觉
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考