Files
Interpreter/Doc/isa/stb文件格式.md
T
Admin ce948451e0 12.9 步骤 0:数据段改 8 字节定宽槽(方案 a)。
- 指令与映像.md / 寄存器码.md:slot 语义 = 槽号(数据偏移 = 槽号 × 8),取消变宽对齐与 global_offset 映射
- Codegen.cpp:删除 width_of/align_up/global_offsets_;layout_data/layout_fb_instances 按槽号布局(字段 = 槽序号)
- stb文件格式.md:line1 真实字节更新(224B、56B 数据段、starter 槽 4/5/6)
- codegen_test:断言更新(槽号化 + 数据区字节数),189 断言 9/9 全绿
2026-08-21 20:01:21 +08:00

118 lines
5.8 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 字节)做真实拆解。
## 概览
- 魔数 `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 内联展开,字段偏移已算进数据段;内建 TON/TOF/CTU 布局冻结在编译器中)。行格式约定:`[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)。