jzcheck
JZ Assembly Static Checker — JZ8 系列 OTP 微控制器汇编静态分析工具。
提供 CLI 链接器(基于 .mpj 项目文件的完整检查)、LSP 服务器(VS Code IDE 集成)、代码格式化器 三大功能。
安装
从源码安装
pip install .
从 .whl 文件安装
先打包生成 .whl 文件:
# 安装构建工具
pip install build
# 构建 wheel 包(产物在 dist/ 目录下)
python -m build --wheel .
或使用项目根目录下的打包脚本(自动清理旧产物):
# Windows
build_jzcheck.bat
安装 .whl 文件:
pip install dist\jzcheck-0.1.0-py3-none-any.whl
也可将 .whl 拷贝到其他机器离线安装:
pip install jzcheck-0.1.0-py3-none-any.whl
卸载:
pip uninstall jzcheck
开发模式安装(源码修改即时生效)
pip install -e .
快速开始
# 检查项目文件(仅支持 .mpj 模式,不支持独立 .asm)
jzcheck project.mpj
# 指定芯片 XML 配置目录
jzcheck -x config/ project.mpj
# 静默模式(只显示 error 和 warning)
jzcheck -q project.mpj
# 警告视为错误
jzcheck -w project.mpj
# 显示详细堆栈分析
jzcheck --stack-detail project.mpj
命令行参数
| 参数 | 说明 |
|---|---|
mpj |
.mpj 项目文件(必填) |
-x / --xml-dir |
芯片 XML 配置目录(默认使用内置 config/) |
-q / --quiet |
静默模式,抑制 info 级别消息 |
-w / --warnings-as-errors |
将警告视为错误 |
--stack-detail |
显示详细堆栈分析路径信息 |
--version |
显示版本号 |
LSP 服务器
jzcheck-lsp
使用 pygls 协议,配合 VS Code 扩展提供 IDE 特性:
| 特性 | 说明 |
|---|---|
| 诊断 | 打开/编辑时实时推送词法、语法、语义、内存诊断 |
| 代码补全 | 指令、寄存器、符号、位索引补全 |
| 悬停信息 | 指令文档、符号定义、宏展开、寄存器位字段 |
| 跳转到定义 | 符号、宏、寄存器的定义位置 |
| 文档符号 | 标签 + EQU 常量的大纲视图 |
| CodeLens | 函数上方显示静态堆栈深度 |
| 代码格式化 | 规范化缩进、大小写、对齐 |
| 符号重命名 | 跨文件标签、EQU 常量、宏名重命名 |
诊断代码
| 代码 | 级别 | 含义 |
|---|---|---|
| E001 | 错误 | 词法错误(无效字符、无效十六进制、无效立即数) |
| E002 | 错误 | 语法错误(未知指令、意外的行首标记) |
| E003 | 错误 | 操作数不匹配 |
| E005 | 错误 | 未定义符号 |
| E006 | 错误 | 重复符号/标签 |
| E011 | 错误 | 宏展开深度超过限制(100 层) |
| E013 | 错误 | 跳转目标超出 ROM 范围 |
| E015 | 错误 | 程序超出 ROM 大小 |
| E016 | 错误 | CALL/JMP 到未定义标签/函数 |
| E999 | 错误 | 内部分析错误 |
| W001 | 警告 | 标识符超过 32 个字符 |
| W003 | 警告 | 宏参数数量不匹配 |
| W005 | 警告 | 堆栈深度达到/超过芯片限制 |
| W007 | 警告 | 递归调用检测 |
| W009 | 警告 | ISR 嵌套风险(中断内启用 EI) |
| W010 | 警告 | 主程序 + 中断组合超过堆栈限制 |
| W011 | 警告 | 函数缺少 RET/RETI/RETL |
| W012 | 警告 | CALL/RET 不平衡 |
| W013 | 警告 | 函数内混合返回类型 |
| W014 | 警告 | ORG 区域重叠 |
| I002 | 信息 | 孤立函数(已定义但从未调用) |
| I003 | 信息 | 流水线进度消息 |
检查内容
词法/语法检查
- 非法字符检测(含编码自动检测 UTF-8/GBK)
- 助记符拼写错误(68 个名称 / 43 个基础助记符 + 24 个 EM78P153 别名 + INT,81 种操作数模式)
- 操作数数量/格式/模式匹配验证
- 数值格式错误(如
0xGG) - 标签名合法性、标识符长度限制(32 字符)
- 三种注释风格:
//、;、/* */
宏处理
- MACRO/ENDM 定义解析,支持参数、嵌套、LOCAL、EXITM
- 参数替换展开(大小写不敏感匹配)
- 嵌套宏递归展开,深度上限保护(100 层)
- 重复宏定义检测、参数数量验证
- 条件指令:
IF/ELSE/ENDIF、IFB/IFNB/IFDEF/IFNDEF/IFIDNI/IFDIFI/ELSEIF - 重复块:
REPT、FOR、FORC - 运行时指令:
ERROR、ECHO、VARARG、EXPAND
语义检查(2-pass 分析)
- 第 1 遍:构建符号表(标签 + EQU 定义)
- 第 2 遍:交叉引用检查、寻址模式验证
- 未定义符号检测、重复定义检测
- ORG 地址跟踪、EQU 表达式求值(支持十六进制/二进制/符号引用/
$PC) - 位操作符号解析(
REG.BIT链式追踪) - 跳转/调用目标范围验证(
$+N/$-N) - EM78P153 兼容别名(24 个)支持
内存检查
- ROM 越界检查(基于芯片配置)
- RAM 分配范围检查(用户 RAM vs 专用寄存器)
- RAM 地址重叠检测、ORG 区域重叠检测
- 用户 RAM 与专用寄存器冲突检查
- 寄存器地址冲突检查
堆栈静态分析(5 阶段)
- 函数构建 + 调用图:按标签分割函数,提取调用关系
- 调用图遍历:路径敏感 DFS 深度计算,循环/递归检测
- 中断分析:ISR 检测、嵌套风险分析
- 泄漏检测:缺失 RET、CALL/RET 平衡、混合返回类型
- 综合报告:主程序 + 中断组合深度、最差路径
代码格式化
- 幂等格式化(
format(format(x)) == format(x)) - 规范化缩进、指令大小写、寄存器大小写、十六进制大小写
- 四列对齐(标签/指令/操作数/注释)
- 对注释无损(含
/* */块注释)
支持的芯片
内置 40 种 JZ8 系列芯片配置(位于 jzcheck/config/),包括:
| 系列 | 型号 |
|---|---|
| JZ8F | 8003, 8620, FT4801, FT8801 |
| JZ8M | 1602, 2532, 2605, 2632, 4600, 4601 |
| JZ8P | 0510, 1503S, 1507, 1510, 1520, 1521, 1525, 153, 1530, 1531, 155, 1611, 2506, 2508, 2521, 2600, 2610, 2612, 2613, 2615, 2616, 5308, 5318, E155E, E255E |
| JZ8PT | 2500, 2503 |
| JZSP | 4001, 4002, 8001 |
默认芯片:JZ8P1520(14 位指令宽度,1024 字节 ROM,80 字节 RAM,5 级堆栈)
支持的语法
- 注释:
//、;、/* ... */ - 立即数:
@前缀(如@0xff、@30、@TCC_NUM) - 数值:十六进制
0x/0X、二进制0b、十进制 - 位寻址:
REG.BIT语法(如FLAG_FUCTION_0.0、STATUS.7) - 相对寻址:
$、$+N、$-N - 伪指令:
EQU、ORG、INCLUDE - 宏:
MACRO/ENDM、LOCAL、EXITM、VARARG、EXPAND - 条件:
IF/ELSE/ENDIF、IFB、IFNB、IFDEF、IFNDEF、IFIDNI、IFDIFI、ELSEIF - 重复:
REPT、FOR、FORC - 运行时:
ERROR、ECHO - 指令集:43 个基础助记符 + 24 个 EM78P153 兼容别名 +
INT= 68 个可识别的名称,共 81 种操作数模式变体
架构
jzcheck/
├── cli.py # CLI 入口 + 流水线编排(.mpj 解析 → 检查)
├── lexer.py # 词法分析器(编码检测 + Tokenizer)
├── parser.py # 语法解析器 + EQU 表达式求值器 + .mpj 解析
├── macro.py # 宏处理器(定义收集 + 参数展开 + 条件指令)
├── semantics.py # 语义分析器(2-pass 符号表 + 寻址检查)
├── memory.py # 内存分配检查器(ROM/RAM/ORG)
├── stack.py # 堆栈深度静态分析器(5 阶段)
├── instructions.py # JZ 指令集数据库(43 助记符 / 81 模式)
├── chipdb.py # 芯片配置数据库(XML 解析 + 查询)
├── reporter.py # 诊断报告引擎(三级 + 定位 + 退出码)
├── includer.py # INCLUDE 路径解析器
├── formatter.py # 代码格式化器(幂等规范化)
├── lsp_server.py # LSP 服务器入口(pygls)
├── lsp_project.py # LSP 工作区管理器(多文件符号管理)
│
├── config/ # 40 种芯片 XML 配置文件
│ ├── JZ8P1520.XML # 默认芯片
│ └── *.XML
│
└── lsp_features/ # LSP 功能模块
├── diagnostics.py # 诊断适配器 + 分析缓存
├── completion.py # 代码补全提供者
├── hover.py # 悬停信息提供者
├── definition.py # 跳转到定义提供者
├── symbols.py # 文档符号提供者
├── codelens.py # CodeLens(堆栈深度显示)
└── rename.py # 符号重命名提供者
数据流
.mpj 项目文件
│
├── parser.parse_mpj() → 芯片型号、源文件列表、头文件列表
├── chipdb.load_chip() → 芯片配置(ROM/RAM/寄存器)
│
├── [头文件预处理 - 共享 MacroProcessor + SemanticAnalyzer]
│ ├── lexer.tokenize_source() → Token 流
│ ├── macro.collect_definitions() → 提取宏定义
│ ├── macro.expand_all() → 展开宏调用
│ ├── parser.parse_lines() → ParsedLine 列表
│ └── semantics.build_symbol_table() → 符号表
│
├── [源文件处理 - 第 1 遍]
│ └── semantics.build_symbol_table() → 收集标签
│
├── [源文件处理 - 第 2 遍]
│ ├── semantics.check_references() → 交叉引用验证
│ ├── memory.check_program() → 内存分配检查
│ └── stack.StackAnalyzer.analyze() → 5 阶段堆栈分析
│
└── reporter.flush() → 排序输出诊断 + 退出码
测试
# 运行全部测试(18 个测试文件)
python -m pytest tests/ -v
# 按模块运行
python -m pytest tests/test_lexer.py -v
python -m pytest tests/test_parser.py -v
python -m pytest tests/test_stack.py -v
python -m pytest tests/test_pipeline.py -v
测试覆盖:词法分析、语法解析、宏处理、语义分析、内存检查、堆栈分析、格式化、诊断适配、CodeLens、重命名、端到端流水线。
已知限制
- 位表达式符号(如
BIT_TCC EQU FLAG_FUCTION_0.0)需要符号表解析才能正确验证位操作指令 - 多文件项目模式下跨文件符号引用需要后续增强
- SONIX 兼容宏库(macro1-3.ash)暂不支持
- 仅支持
.mpj项目模式,不支持独立的.asm文件检查
许可证
MIT
Release files for jzcheck 0.9.3
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| jzcheck-0.9.3.tar.gz | 279.1 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| jzcheck-0.9.3-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 550.3 kB
Release files / jzcheck-0.9.3.tar.gz
| Download URL | jzcheck-0.9.3.tar.gz |
|---|---|
| Size | 279.1 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
e420fd98ab3df75b09b4651f84158a1ab78f649b719168970854651473fd5859
|
|
BLAKE2b-256 checksum How to use checksums |
b596b0a8d1b79174b0da56b751d1f1e9b37150921c7d77e016db5bcbed19d66c
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.12.0
|
Release files / jzcheck-0.9.3-py3-none-any.whl
| Download URL | jzcheck-0.9.3-py3-none-any.whl |
|---|---|
| Size | 271.1 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
fe6d16c5aaa409ba93ad38ce56caf81720fa5633a78b06e5a7f692daadbdb5e4
|
|
BLAKE2b-256 checksum How to use checksums |
66a063caa05d9a49ab146ae47077f71154668e7fd3296ad33a4d629f476e0986
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.12.0
|