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

6.1 KiB
Raw Blame History

.stb 映像文件结构

编译产物 .stb面向使用者的结构说明。规范以 指令与映像.md 为准,本文用 line1.stb224 字节)做真实拆解。

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]tag0=BOOL、1=INT、2=TIME。

line1 无字面量常量 → 段为空(offset_const == offset_funcs)。

函数表段(offset_funcs 起)

一行 12 字节:[nregs:u32][code_offset:u32][code_len:u32]

  • 行下标即 fn_idcode_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
  • CALLfn_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

用工具验证

  • ctestisa_roundtrip / codegen_slice1 覆盖编解码往返与映像校验
  • isa::ImageView 提供只读视图(校验魔数/版本/段边界/入口 fn_id)
  • 手工检查:xxd line1.stb 对照上表逐段核对

与执行器的关系

BytecodeExecutor12.9/12.10 实现)只读本格式:头(cycle_limit/dt_ms)、函数表(帧 nregs + 代码定位)、数据段(全局 + FB 实例状态)。I/O 绑定不在映像里,在 sidecar <name>.runtime.tomlvar → 槽号 → channel/bit)。