Files
Interpreter/Doc/isa/stb文件格式.md
T
Admin a308ae713d 阶段 B 步骤 6:.stb 写侧新格式(头 104 + 型号标识 + SHA-256 文件尾)。
- Stb:kHeaderSize 104、kSha256Size 32;SHA-256 实现(FIPS 180-4,含标准测试向量验证);
  fill_model_id(name+version 拼 32 字节补 '\0');StbView 解析新格式 +
  model_id()/model_matches()/sha_ok()(数据段不含尾、缺尾报错)
- Codegen:assemble_image 写型号标识(偏移 72)+ 文件尾 SHA-256
- main.cpp:--disasm 显示 model/sha;写后自检(ok+sha+型号匹配,失败报错)
- 测试:machine_test +SHA-256 已知向量(空串/abc)与型号标识断言(53 断言);
  codegen_test data_len 断言 +32(SHA 尾);ctest 12/12
- 验证:line1 288 字节 model=STATOR1 sha=ok;篡改一字节 sha=BAD
2026-08-21 22:20:35 +08:00

120 lines
6.1 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# .stb 映像文件结构
编译产物 `.stb` 的**面向使用者**的结构说明。规范以 [`指令与映像.md`](指令与映像.md) 为准,本文用 `line1.stb`224 字节)做真实拆解。
> **12.13 修订**(编译器写侧已落地,vm 读侧待步骤 8):头新增型号标识[32](头 72 → 104 字节,段偏移基准同步后移),文件尾新增 SHA-256[32](对文件尾之前全部内容计算)。line1 产物现为 288 字节。本文拆解仍为旧格式数字,需在 vm 侧落地后统一重新生成。
## 概览
- 魔数 `STSC`,版本 `1`**全部整数小端**
- 文件 = 头 + 五个段,段序:**常量表 → 函数表 → 字节码 → FB 布局 → 数据**
- 段偏移记在头里;`offset_const ≤ offset_funcs ≤ offset_code ≤ offset_fb ≤ offset_data ≤ 文件长度`
```
┌──────────────────────────────────────────────────┐
│ 头(72 字节,偏移 0) │
├──────────────────────────────────────────────────┤
│ 常量表段 offset_const .. offset_funcs │
├──────────────────────────────────────────────────┤
│ 函数表段 offset_funcs .. offset_code │
├──────────────────────────────────────────────────┤
│ 字节码段 offset_code .. offset_fb │
├──────────────────────────────────────────────────┤
│ FB 布局段 offset_fb .. offset_datav1 为空)│
├──────────────────────────────────────────────────┤
│ 数据段 offset_data .. 文件末尾 │
└──────────────────────────────────────────────────┘
```
## 头(72 字节)
| 偏移 | 宽 | 字段 | line1 实际值 |
|---|---|---|---|
| 0 | 4 | 魔数 `STSC` | `53 53 54 43` |
| 4 | 4 | 版本 `1` | 1 |
| 8 | 4 | `cycle_limit`(每周期指令上限) | 100000 |
| 12 | 4 | `dt_ms`(本周期 Δt | 10 |
| 16 | 8 | 工程哈希(FNV-1a 64 | `0xc3fe4ae74ad45900` |
| 24 | 4 | 入口 `entry_fn_id` | 1MAIN |
| 28 | 4 | 全局槽数 `n_globals` | 4 |
| 32 | 4 | I 槽数 `n_i` | 0v1 不拆) |
| 36 | 4 | Q 槽数 `n_q` | 0 |
| 40 | 4 | M 槽数 `n_m` | 0 |
| 44 | 4 | 常量数 `n_consts` | 0 |
| 48 | 4 | 函数数 `n_funcs` | 2 |
| 52 | 4 | `offset_const` | 72 |
| 56 | 4 | `offset_funcs` | 72 |
| 60 | 4 | `offset_code` | 96 |
| 64 | 4 | `offset_fb` | 168 |
| 68 | 4 | `offset_data` | 168 |
## 常量表段(`offset_const` 起)
一行 12 字节:`[tag:u32][value:u64]``tag`0=BOOL、1=INT、2=TIME。
line1 无字面量常量 → 段为空(`offset_const == offset_funcs`)。
## 函数表段(`offset_funcs` 起)
一行 12 字节:`[nregs:u32][code_offset:u32][code_len:u32]`
- **行下标即 `fn_id`**`code_offset` 相对字节码段起点(**字节**);`code_len` 为**指令条数**
- 入口 = 头的 `entry_fn_id` 指向的行
line12 行):
| fn_id | nregs | code_offset | code_len | 内容 |
|---|---|---|---|---|
| 0 | 8 | 0 | 1 | `MotorStarter` 占位(内联展开,仅 RET |
| 1 | 13 | 4 | 17 | `MAIN` |
## 字节码段(`offset_code` 起)
指令 4 字节一条:`[op:8 | rd:8 | a:8 | b:8]`(小端 u32)。
- `rd` 目的寄存器;`a|b` 视操作码为寄存器、槽号(u16)或跳转偏移(有符号 int16,**相对下一条指令**:目标 = 当前 + 1 + off
- `CALL``fn_id` = 函数表行下标
- 调用约定:结果 r0、参数 r1..r7、变量与临时 r8 起
line1 `MAIN` 前 5 条(`0x60` 起,slot 为 8 字节定宽槽号):
| 偏移 | 字节 | 反汇编 | 含义 |
|---|---|---|---|
| 0x64 | `12 08 01 00` | `LOAD_I r8, 1` | I0_0io.input 绑定 → LOAD_I,槽 1 |
| 0x68 | `17 08 04 00` | `STORE_GLOBAL r8, 4` | starter.start(槽 4)← I0_0 |
| 0x6C | `16 09 02 00` | `LOAD_GLOBAL r9, 2` | I0_1(槽 2 |
| 0x70 | `17 09 05 00` | `STORE_GLOBAL r9, 5` | starter.stop(槽 5)← I0_1 |
| 0x74 | `16 08 04 00` | `LOAD_GLOBAL r8, 4` | 内联体:读 starter.start(槽 4 |
## FB 布局段(`offset_fb` 起)
v1 为空(用户 FB 内联展开,字段偏移已算进数据段;内建 8 个 FB 布局冻结在编译器中(12.11 扩充))。行格式约定:`[field_count:u32][field_count × (tag:u32, offset:u32)]`offset 相对实例基址。
## 数据段(`offset_data` 起)
**每槽 8 字节定宽**12.9 方案 a):`BOOL` 用低 1 字节、`INT` 用低 2 字节(小端)、`TIME` 全 8 字节。指令 `slot` 操作数即**槽号**,数据偏移 = 槽号 × 8。
槽序:**全局块**`n_globals` 个,声明序)→ **FB 实例块**(POU 收集序、实例声明序,每字段一槽)。
line1 数据段(56 字节 = 7 槽 × 8B,`0xA8` 起):
| 槽号 | 偏移 | 内容 |
|---|---|---|
| 0 | 0xA8 | EmergencyStopBOOL,初值 0 |
| 1 | 0xB0 | I0_0BOOL |
| 2 | 0xB8 | I0_1BOOL |
| 3 | 0xC0 | Q0_0BOOL |
| 4 | 0xC8 | starter.startBOOL |
| 5 | 0xD0 | starter.stopBOOL |
| 6 | 0xD8 | starter.qBOOL |
## 用工具验证
- `ctest``isa_roundtrip` / `codegen_slice1` 覆盖编解码往返与映像校验
- `isa::ImageView` 提供只读视图(校验魔数/版本/段边界/入口 fn_id)
- 手工检查:`xxd line1.stb` 对照上表逐段核对
## 与执行器的关系
`BytecodeExecutor`12.9/12.10 实现)只读本格式:头(`cycle_limit`/`dt_ms`)、函数表(帧 `nregs` + 代码定位)、数据段(全局 + FB 实例状态)。I/O 绑定**不在**映像里,在 sidecar `<name>.runtime.toml`var → 槽号 → channel/bit)。