☰
xqcli:XQuad 工具链统一命令行 `xquad` 使用与源码级解析
2026/10/13 2:57:21 网站建设 项目流程

【免费下载链接】xquad

A rust implementation of the Quip Network's quantum virtual machine.

项目地址:https://gitcode.com/gh_mirrors/xq/xquad
点击查看免费下载

本文是 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 中:

  1. 读取输入源文件;
  2. 调用xqasm::parse将源码解析为指令行(xqasm/src/lib.rs 中定义,每条源行可包含;注释、name:标签定义与MNEMONIC [operands...]指令,操作数支持r0~r255寄存器、42/-99/0xFF整型字面量与标签引用);
  3. 调用xqasm::assemble生成xqvm::Program;
  4. 调用program.encode()得到二进制字节码;
  5. 按--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 中定义。执行流程为:

  1. 读取FILE字节;若指定--text,则先按 UTF-8 校验并调用xqasm::assemble_source(xqasm/src/lib.rs 提供的 parse + assemble 一步入口)就地汇编;否则调用xqvm::Program::decode解码字节码;
  2. 构造xqvm::Vm,通过链式调用set_calldata(...)、set_output_slots(...)、set_step_limit(...)/set_unlimited_steps()、set_memory_limit(...)配置虚拟机;
  3. 根据是否启用--trace,调用vm.run(&program)或vm.run_trace(&mut tracer, &program)执行;
  4. 执行结束后打印输出槽(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
UninitRegisterPhaseCFG 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.xqb

xquad 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.

项目地址:https://gitcode.com/gh_mirrors/xq/xquad
点击查看免费下载

相关推荐

上一篇:基于 Fresh 与 Supabase 实现 PKCE 认证流程:从注册、登录到路由守卫的完整实战
下一篇:tensortrade 浮点流排序操作(Ordering)API 深度指南:clamp、min 与 max 的实现原理与实战用法

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询