SlimeASM-rev — Linux ELF x86_64 binary → ASM + C 逆変換
tag 無しバイト列の native ELF を、NASM ソースと C ソースに bit-exact で復元。
銀行・防衛・組込で「source-lost / vendor-lost」となった Linux x86_64 native binary を、
NASM intel ソース + C ソースの双方 に bit-exact で逆変換します。
出力 NASM は nasm + ld で再 assemble して原 binary と同じ動作を、
出力 C は gcc -O0 -nostdlib -static で本物の native ELF を生成して同じ動作を、
それぞれ 実機で再生成 + 実行 + stdout 完全一致 という最も厳しい round-trip 軸で証明します。
- Phase A: ELF64 minimal parser + x86_64 命令デコーダ (整数 hot-loop subset 約 14 種) + NASM intel emitter + 直線 C emitter
- Phase B 入口: CFG 復元 (Cooper-Harvey-Kennedy iterative dominator + Aho/Sethi natural loop body) + 構造化 C (
do { ... } while (R[1] != 0);+if/elsediamond) - Phase B (b): 関数境界復元 (prologue/epilogue + call/ret + 自己再帰)。各関数を独立 C function として emit、call → C 呼出、ret → return; に翻訳
- Phase B (d): inter-procedural Slot IR — 関数 = Slot ノード、call graph を first-class IR edge として昇華、JSON deterministic round-trip、自己再帰も自然表現
- S9 bench で Linux ELF 全 8 軸 200/200 + Windows PE32+ 全 8 軸 152/152 = 合算 352/352 PASS(2026-05-19 実測)、ELF 25 sample (NASM 直書き 8 + gcc -O0 -nostdlib -static 起点 17) + PE 19 sample (msvcrt + kernel32 統合) で ASM/C 両方の round-trip 全 PASS。SIB byte / movzx / movsx / cdqe / cdq / movsxd / cqo / shl-shr-sar / 2D 配列 / struct field offset / nested loop / 再帰 fact(4) / libc-linked msvcrt!puts まで網羅
- Phase D — Windows PE32+ x86_64 対応: PECOFF v8.3 準拠 parser + DLL import 解決 (IAT slot → 関数名) + Win64 ABI (rcx/rdx/r8/r9 + shadow space [rsp+0x20]) + WinAPI recipe table。Linux ELF と同じ 8 軸 round-trip 監査を Microsoft レガシー .exe / .dll で実現
銀行 IBM Linux x86_64 / 防衛 ELF binary 系の 「source 喪失 native binary」 を、
決定論的変換 + 8 軸 round-trip 自動回帰 + 監査 chain で扱う逆変換器。
SlimeNENC ファミリーで初めての 逆方向 製品 — 既存の forward 系 (COBOL/HLASM/MASM/MUMPS/PL/I/RPG/FORTRAN/Natural) と対をなします。
主要計測値 (2026-05-19 実測)
= ALL AXES PASS (44 sample)
= NASM 直書き 8 本 + gcc -O0 起点 17 本
= msvcrt + kernel32 統合、再帰 + libc-linked 含む
Linux (NASM/ld + GCC) + Windows (NASM/mingw + GCC)、全て実機検証
ELF / PE 統一 IR、call graph を first-class edge、自己再帰自然表現
SIB / movzx / movsx / cdqe / movsxd / shl-shr-sar / and-or 等、Linux/Windows 共通
市場文脈 — source 喪失 native binary が残る場所
| 銀行 (Linux x86_64) | 移行プロジェクトで「source code が見つからない / 保守ベンダー消滅」した native ELF / .so library。Heirloom / Astadia 等は HLASM mainframe 専門で Linux native binary は対象外。 |
|---|---|
| 防衛・宇宙 | 10-30 年無修正の closed binary (組込 Linux ELF / 計測機 daemon)。発注元から source 提供を受けられないが C ソース化 + 監査 chain が要求される。 |
| 組込・医療機器 | FDA / PMDA / IEC 62304 認証で「ソフトウェアの完全な記述」が義務化されている領域。binary しかないコンポーネントを C 化して 監査人が再現可能なドキュメント に。 |
| レガシー documentation | 「動いているが誰も触れない」 daemon を C 化して static analysis / SBOM / CVE 監査の対象に。 |
| 競合状況 | Ghidra (NSA OSS) / IDA Pro / Hex-Rays / RetDec などが既存。SlimeASM-rev は (1) 決定論 + 8 軸 round-trip 自動回帰 で「変換が情報を捨てていない」ことを bench harness で証明、(2) Linux ELF + Windows PE32+ の単一統一 IR (Slot IR) で OS をまたいだ監査可能、(3) decompile 結果がそのまま gcc/mingw でビルドでき、原本と stdout 完全一致する点が他のどの decompiler も持っていない差別化軸。Hex-Rays は静的 C を出すが build + run の保証はしない。 |
S9 bench 全 8 軸 — Linux ELF 200/200 + Windows PE32+ 152/152 = 合算 352/352 PASS
同一の S9 bench harness が Linux ELF と Windows PE32+ 両方を bit-level 厳密に検証。Phase B 構築の x86_64 命令デコーダ (~37 種 opcode) を 両 OS 共通で流用し、container 層 (PE32+ parser / DLL import / Win64 ABI) のみ差し替える設計。
Linux ELF 25 sample 内訳
| 軸 1a dialect-detect | ELF magic + ELFCLASS64 + EM_X86_64 (e_machine = 0x3E) を tokenizer が認識。25/25 PASS。 |
|---|---|
| 軸 1b opcode-recover | .text セクション全 1,397 命令 (25 sample 計、NASM 177 + gcc 1,220) で db 0xNN fallback ゼロ。25/25 PASS。 |
| 軸 2 mutation-detect | .text 1 bit 反転 5 trial × 25 sample = 125 trial、125/125 全検出。disasm 出力に必ず差分が出る不変条件。 |
| 軸 3 determinism | NASM 出力を 2 回 emit して byte-equal を全 25 sample で確認。25/25 PASS。 |
| 軸 4 ASM round-trip | emit NASM → nasm + ld → 実行 → 原 ELF と stdout 完全一致。実 native binary を 2 系統 (オリジナル / 我々が再生成) で実行して比較する最も厳しい軸。25/25 PASS (再帰 fact(4) = 24、2D 配列 nested loop、struct field offset、SIB byte 配列インデックス すべて含む)。 |
| 軸 5 C round-trip | emit C → gcc -O0 -nostdlib -static → 実行 → 原 ELF と stdout 完全一致。直線 PC dispatch + byte-addressable STACK[] 経由で call/ret/push/pop も bit-faithful。25/25 PASS。 |
| 軸 6 構造化 C round-trip | CFG 復元 + 構造化 C (do-while + if/else + 関数単位 + call → C call + ret → return;) → gcc → 実行 → stdout 完全一致。25/25 PASS (nested loop 含む)。 |
| 軸 7 Slot IR round-trip | SlotImage → JSON → SlotImage → 構造的 equality + JSON byte-equal の二重チェック。関数 = Slot ノード、call graph も含めて完全保持。25/25 PASS。 |
Windows PE32+ 19 sample 内訳 (同じ 8 軸を bit-level 厳密に再現)
| 軸 1a PE dialect-detect | DOS magic "MZ" + PE signature "PE\0\0" + COFF Machine=0x8664 (IMAGE_FILE_MACHINE_AMD64) + Optional Header Magic=0x20B (PE32+) + Subsystem=3 (CONSOLE) を bit-level に検証。19/19 PASS。 |
|---|---|
| 軸 1b opcode-recover | .text セクション (VirtualSize 制限の live 領域) 全命令で db 0xNN fallback ゼロ。19/19 PASS。 |
| 軸 2 mutation-detect | .text 1 bit 反転 5 trial × 19 sample = 95 trial、95/95 全検出。 |
| 軸 3 determinism | 同一 .exe を 2 回 disasm → byte-equal を全 19 sample で確認。19/19 PASS。 |
| 軸 4 ASM round-trip | emit NASM → nasm -fwin64 → mingw-link (-lmsvcrt -lkernel32) → 実 .exe → WSL2 binfmt 実行 → 原 .exe と stdout 完全一致。IAT 参照は extern __imp_FUNC で再現、リンカが PE import table を再生成。19/19 PASS。 |
| 軸 5 C round-trip | emit C → mingw-gcc -nostdlib -e _start → 実 .exe → stdout 完全一致。mov reg, qword [rip+iat]; call reg の IAT 経由 indirect call は peephole で call_iat <FUNC> 1 命令に折り畳み → Win64 ABI 引数を rcx/rdx/r8/r9/[rsp+0x20] から取り出して kernel32 / msvcrt 関数を直接呼び出すリチピ展開。19/19 PASS。 |
| 軸 6 構造化 C round-trip | CFG 復元 + do-while/if-else + 関数単位 → mingw → 実行 → 一致。19/19 PASS。再帰 fact(4) = 24 含む。 |
| 軸 7 Slot IR round-trip | Linux ELF と 完全同一の Slot IR スキーマで PE32+ binary も SlotImage 化。各関数が SlotFunction ノード、call graph も保持。19/19 PASS。06_call_simple (2fn/1call) / 07_two_funcs (3fn/2call) / 08_recursion (2fn/2call、self-loop edge) など ELF 側と完全一致する関数構造を復元。 |
PE32+ 固有の対応 (Phase D)
- PECOFF v8.3 parserDOS header (64B、magic MZ + e_lfanew @ 0x3C) → PE signature (4B) → COFF header (20B、Machine=0x8664 必須) → Optional Header (PE32+ 240B、Magic=0x20B 必須) → Section Table を bit-level に解析、VirtualSize で .text の live 領域を制限
- DLL import 解決DataDirectory[1] Import Table を walk:
_IMAGE_IMPORT_DESCRIPTORarray + INT/IAT thunk array (8B, ordinal flag = bit 63) + Hint/Name table を解読、IAT slot の VA → DLL 名 + 関数名を確定。例:0x140003070 → msvcrt.dll!puts - IAT call peepholegcc -O0 + MinGW が頻発させる
mov reg, qword [rip+iat]; call reg2 命令ペアを 1 つのcall_iat <FUNC>仮想命令に折り畳み、Win64 ABI 経由で C 直接呼び出しに lower - Win64 ABI recipe引数: rcx (R[1]) / rdx (R[2]) / r8 (R[8]) / r9 (R[9]) / 5th =
mem_r(R[4]+0x20, 8)。文字列引数 (LPCSTR) は仮想 VA から mem_r で 1 byte ずつ実バイトを取り出し local バッファに復元してから kernel に渡す - WinAPI recipe table (拡張可)現状 5 関数 — kernel32: GetStdHandle / WriteFile / ExitProcess / lstrlenA、msvcrt: puts。新 API 追加は 3 ステップ完結 (PROLOGUE dllimport 宣言 + recipe table 追加 + link command に
-l<dll>)、decoder / CFG / Slot IR には触らない - trailing thunk trimMinGW が .text 末尾に置く
jmp qword [rip+iat]thunk テーブルは SlotImage に含めない (関数誤認識防止)。再 link 時にリンカが新しい thunk を再生成
サンプル一覧 (合算 44 本) — Linux ELF 25 + Windows PE32+ 19
研究 PoC の NASM 直書き 8 本 (Linux) に加え、production 訴求として real-world C ソースから gcc -O0 -nostdlib -static でビルドした native ELF 17 本 と x86_64-w64-mingw32-gcc -nostdlib -e _start でビルドした PE32+ .exe 19 本 も全 8 軸で PASS。配列インデックス (SIB byte)、符号付き/符号なし拡張 (movsx/movzx/movsxd/cdq/cdqe)、ビット演算 (shl/shr/sar/and/or)、ネストループ、2D 配列、struct field offset、再帰、libc-linked (msvcrt!puts / kernel32!lstrlenA) まで網羅。SSE2-4 (XMM 浮動小数点) は次フェーズで拡張予定。
NASM 直書き 8 本 (研究 PoC、手書き整数 hot-loop subset)
| 01 hello | syscall write で "Hello, ELF!\n" 出力。1 BB / 8 命令の最小 ELF。 |
|---|---|
| 02 arith | 17 + 25 = 42 を 2 桁 ASCII で出力。idiv + add al + mov [rip+disp] 等。 |
| 03 loop | loop sum_loop 命令で 1+2+3+4+5 = 15。CFG に back edge、構造化 C は do { ... } while (R[1] != 0); で復元。 |
| 04 branch | cmp + jge diamond。構造化 C は if (cond) { ... } else { ... } で復元、共通 join BB に合流。 |
| 05 compute | imul rax, rbx で 6 × 7 = 42。 |
| 06 call_simple | _start → do_print。prologue (push rbp; mov rbp, rsp) + epilogue (pop rbp; ret) を関数境界として認識、独立 C function に分離。 |
| 07 two_funcs | 3 関数 (_start → add_two + print_dec)。call graph に 2 inter-procedural edge。 |
| 08 recursion | factorial(4) = 24 を自己再帰で計算。call graph に self-loop edge (fact → fact)、push rbx / pop rbx で caller-saved spill を STK[] 経由で bit-faithful 保持。 |
gcc -O0 -nostdlib -static 起点 17 本 (production 訴求、real-world C ソース)
| 01 hello (gcc) | freestanding C で "Hello, gcc -O0!\n"。35 命令、byte-addressable STACK[65536] + entry_pc 補正で call sys3 + call sys_exit も bit-faithful。 |
|---|---|
| 02 arith (gcc) | 17 + 25 = 42。cqo + idiv による真の符号付き除算経路、add [rbp-disp], rax 等の memory-destination 算術。69 命令。 |
| 03 loop (gcc) | for ループで 1+2+3+4+5 = 15。cmp [rbp-disp], imm + jle rel8 のループヘッダ、add [rbp-disp], 1 でカウンタ更新。71 命令。 |
| 04 branch (gcc) | if (x >= 5) 分岐。mov QWORD PTR [rbp-disp], imm / leave 命令を含む完全な C 関数 epilogue 構造。46 命令。 |
| 05 compute (gcc) | 6 × 7 = 42。2-op imul による乗算、複数 syscall 呼出を含む 68 命令。 |
| 06 call_simple (gcc) | _start から static void do_print(void) 呼出 + sys_exit。3 関数 (sys3 / sys_exit / do_print) の境界復元。41 命令。 |
| 07 two_funcs (gcc) | add_two() + print_dec() の 2 ヘルパ関数。call graph に 5 関数ノード、関数間の引数受け渡し (rdi 経由) も bit-faithful。84 命令。 |
| 08 recursion (gcc) | C で書いた fact(4) = 24 再帰。手書き NASM 版と同じく self-loop edge を call graph に検出。85 命令。 |
| 09 array_sum (gcc) | arr[5] = {3,5,7,9,11} 配列合計 → SUM=35。SIB byte mov rax, [rax*8+0x402000] による配列インデックスアクセス。72 命令。 |
| 10 strlen (gcc) | 手書き strlen で "Hello, World!\n" の長さを計測 → LEN=14。movzx eax, BYTE PTR [rax] (zero-extend) + test al, al による null-terminator ループ。81 命令。 |
| 11 signed_array (gcc) | signed char 配列 {-3, 5, -8, 12, 4} の合計 → SUM=10。movsx rax, al (sign-extend) + 符号付き演算。74 命令。 |
| 12 int_index (gcc) | int i による配列ループ + 3 桁出力 → SUM=150。cdqe (eax→rax sign-extend) + 32-bit op variants (gcc -O0 が int ローカル変数で頻出する mov DWORD PTR / cmp DWORD PTR 等)。89 命令。 |
| 13 bitshift (gcc) | 32 << 3 = 256, >> 1 = 128 → VAL=128。shl/shr/sar (REX.W C1 /N imm8、D1 /N 1-bit) によるビットシフト演算。86 命令。 |
| 14 bitmask (gcc) | 0xFF12 & 0xFF = 18 → RES=18。and r/m64, imm8 (REX.W 83 /4 sign-ext imm8) によるビットマスク。65 命令。 |
| 15 stride (gcc) | ストライド配列 arr[i*3] 合計 → STR=35。i*3 計算 (gcc -O0 は mov rax,i; add rax,rax; add rax,i で展開) + SIB アクセスの組合せ。72 命令。 |
| 16 matrix (gcc) | 3×4 行列の nested loop 合計 → MAT=78。2D 配列 + ネスト CFG。lea rdx, [rax*4+0x0] (SIB lea) で row offset を計算。85 命令。 |
| 17 struct (gcc) | struct 配列 pts[3] = {{10,20},{30,40},{50,60}} の field 合計 → PT=210。SIB + displacement による field offset (各 pts[i].x / pts[i].y) アクセス。107 命令。 |
Windows PE32+ 19 sample (mingw-gcc -O0 -nostdlib -e _start)
Linux ELF 17 sample と機能等価な C ソースを x86_64-w64-mingw32-gcc でビルドした PE32+ .exe を、同じ 8 軸 round-trip 監査に通したもの。IAT 経由 indirect call (mov rax, qword [rip+iat]; call rax) を peephole で call_iat <FUNC> に折り畳み、Win64 ABI 経由で kernel32 / msvcrt 関数を直接呼び出す形で C を復元。WSL2 binfmt 直接実行で stdout 検証。
| 01 hello (PE) | GetStdHandle + WriteFile + ExitProcess → Hello, PE!。最小 IAT 3 関数の Win64 ABI 呼び出し。 |
|---|---|
| 02 arith (PE) | 17+25 = 42 を 2 桁 ASCII で WriteFile 出力 → SUM=42。cqo + idiv rsi による真の符号付き除算。 |
| 03 loop (PE) | for ループで 1+2+3+4+5 = 15 → SUM=15。cmp DWORD PTR + jle ループ + WriteFile。 |
| 04 branch (PE) | if (x >= 5) 分岐 (x=7) → big。両 arm で別文字列を WriteFile、共通 join に合流。 |
| 05 compute (PE) | 6 × 7 = 42 → PROD=42。2-op imul rax, rbx + idiv。 |
| 06 call_simple (PE) | _start → do_print(handle)。Win64 ABI の rcx 引数渡し + 内部 WriteFile。 |
| 07 two_funcs (PE) | add_two() + print_dec(handle, val) の 2 ヘルパ関数。SlotImage に 3 関数ノード + 2 inter-procedural edge。 |
| 08 recursion (PE) | factorial(4) = 24 自己再帰 → FACT=24。call graph に fact → fact self-loop edge、Win64 shadow space [rsp+0x20] を介した callee-saved 保持。 |
| 09 array_sum (PE) | arr[5] = {3,5,7,9,11} 合計 → SUM=35。SIB byte mov rax, [rax*8+0x140002000] による配列インデックス。 |
| 10 strlen (PE) | 手書き strlen で "Hello, World!\n" → LEN=14。movzx eax, BYTE PTR [rax] + test al, al による null-terminator ループ。 |
| 11 signed_array (PE) | signed char 配列 {-3, 5, -8, 12, 4} 合計 → SUM=10。movsx rax, al + 符号付き演算。 |
| 12 int_index (PE) | int i 配列ループ + 3 桁出力 → SUM=150。cdqe (eax→rax sign-extend) + 32-bit op variants + 100/10 の 2 段除算。 |
| 13 bitshift (PE) | 32 << 3 = 256, >> 1 = 128 → VAL=128。shl/sar r32 (32-bit op variants 含む) によるビットシフト。 |
| 14 bitmask (PE) | 0xFF12 & 0xFF = 18 → RES=18。and r/m64, imm8 によるビットマスク。 |
| 15 stride (PE) | ストライド配列 arr[i*3] 合計 → STR=35。add + add 展開による i*3 計算 + SIB アクセス。 |
| 16 matrix (PE) | 3×4 行列 nested loop 合計 → MAT=78。2D 配列 + ネスト CFG、lea rdx, [rax*4+0x0] (SIB lea) で row offset 計算。 |
| 17 struct (PE) | struct 配列 pts[3] = {{10,20},{30,40},{50,60}} field 合計 → PT=210。SIB + displacement field offset アクセス。 |
| 18 msvcrt_puts (PE) | libc-linked binary 初の sample。msvcrt!puts("Hello, msvcrt!") + kernel32!ExitProcess → Hello, msvcrt!。kernel32 以外の DLL import を扱う設計 scalable を実証。 |
| 19 lstrlenA (PE) | kernel32!lstrlenA("Hello, libc!") で長さ 12 を取得、msvcrt!puts で 2 桁出力 → LEN=12。2 DLL (kernel32 + msvcrt) からの import を 1 binary で。 |
変換例 1 — ループの構造化 C 復元 (sample 03)
原 NASM の loop sum_loop 命令で 1+2+3+4+5 を計算する自己ループ。CFG に back edge が現れ、SlimeASM-rev は natural loop body 検出 + 単一 BB self-loop with `loop` 命令 → do { ... } while (R[1] != 0); パターンで構造化 C を復元します:
; Original NASM (sample 03, ループ部のみ抜粋)
xor rax, rax
mov rcx, 5
sum_loop:
add rax, rcx
loop sum_loop ; dec rcx; jnz sum_loop
// SlimeASM-rev 復元 C (構造化)
R[0] = R[0] ^ R[0]; // xor rax, rax
R[1] = 0x5; // mov rcx, 5
do {
R[0] = R[0] + R[1]; // add rax, rcx
/* e2 fb loop sum_loop (terminator absorbed) */
R[1] = R[1] - 1;
} while (R[1] != 0);
loop 命令の back edge を Cooper-Harvey-Kennedy iterative dominator が検出、Aho/Sethi natural loop body 解析が単一 BB self-loop と認識し、構造化 do-while で復元 — goto 不要。
変換例 2 — if/else 分岐の構造化 C 復元 (sample 04)
原 NASM の cmp + jge で分岐し、両 arm が共通 join BB に合流する diamond パターン。SlimeASM-rev は cond BB + 2 succs → 共通 join → if (cond) { ... } else { ... } として構造化:
; Original NASM (sample 04, 分岐部)
mov rax, 7
cmp rax, 5
jge is_big
; small branch
... write "small\n" ...
jmp done
is_big:
... write "big\n" ...
done:
... exit ...
// SlimeASM-rev 復元 C (構造化、共通 join に合流)
R[0] = 0x7; // mov rax, 7
{ int64_t _diff = (int64_t)R[0] - (int64_t)5;
ZF = (_diff == 0); SF = (_diff < 0); }
OF = 0;
/* 7d 1a jge is_big (terminator absorbed) */
if (SF == OF) { // jge 条件
/* big arm */
... write "big\n" ...
} else {
/* small arm */
... write "small\n" ...
}
/* done: 共通 join BB → exit */
diamond 検出は intra-function dominator + post-dominator 同居判定。jmp による合流は emitter 側で吸収、goto 不要で純粋な C if/else に復元。
変換例 3 — 関数単位 + 自己再帰のショーケース (sample 08)
factorial(4) = 24 を自己再帰で計算する 6 BB の関数。CFG 的に純粋なループでも単純 diamond でもない (cond + 各 arm が独立 ret) ため、構造化 C 内には goto BB_xxxx; ラベル参照が残りますが、これは 関数境界復元 + call → C call + ret → return; + caller-saved spill (push rbx / pop rbx) を STK[] 経由で bit-faithful 保持 + 自己再帰 の同梱ショーケースとして掲載:
; Original NASM (sample 08, fact 関数)
fact:
push rbp
mov rbp, rsp
cmp rbx, 1
jg recurse
mov rax, 1 ; base: 1! = 1
pop rbp
ret
recurse:
push rbx ; spill rbx across recursive call
sub rbx, 1
call fact ; rax := (rbx-1)!
pop rbx ; restore rbx
imul rax, rbx ; rax := rbx * (rbx-1)!
pop rbp
ret
// SlimeASM-rev 復元 C (関数単位、自己再帰、caller-saved spill 保持)
static void func_401060(void) { // fact()
BB_401060:;
STK[--RSP_IDX] = R[5]; // push rbp
R[5] = R[4]; // mov rbp, rsp
/* cmp rbx, 1 */
if (ZF == 0 && SF == OF) goto BB_401071; // jg recurse
BB_40106a:;
R[0] = 1; // mov rax, 1
R[5] = STK[RSP_IDX++]; // pop rbp
return; // ret → C return
BB_401071:;
STK[--RSP_IDX] = R[3]; // push rbx
R[3] -= 1; // sub rbx, 1
func_401060(); // call fact → C 呼出 (自己再帰)
R[3] = STK[RSP_IDX++]; // pop rbx
R[0] = R[0] * R[3]; // imul rax, rbx
R[5] = STK[RSP_IDX++]; // pop rbp
return;
}
この C を gcc -O0 -nostdlib -static でコンパイルして実行すると、原 ELF と 同じ stdout (FACT=24) を出力 — 軸 6 構造化 C round-trip PASS。複雑 CFG (cond + 各 arm 独立終端) は Phase B 残工程の多 BB ループ + tail duplication 拡張で goto 排除予定。
関数 = Slot ノード、call graph IR 昇華 (Phase B (d))
SlimeNENC ファミリー共通の Slot IR (Core64 + Ext32 固定 bit、請求項 11) を逆方向にも適用。各関数が SlotFunction ノードとして第一級オブジェクトになり、call edges も first-class IR 構造 として保持されます (callee 関数名のリスト)。自己再帰も自然に self-loop edge として表現:
| sample | functions | call edges |
|---|---|---|
| 01-05 (linear) | 1 | 0 |
| 06 call_simple | 2 | 1 (_start → func_40100f) |
| 07 two_funcs | 3 | 2 (_start → func_401014, _start → func_401027) |
| 08 recursion | 2 | 2 (_start → func_401060, func_401060 → func_401060) |
SlotImage 全体は deterministic な JSON に encode/decode 可能 (軸 7 round-trip)。これにより、call graph と関数構造を保持したまま 外部ツールチェーン (audit DB / SBOM / static analysis) と連携 できます。
監査適合性 (金融・防衛・医療機器)
- Bit-exact同一 ELF 入力 → 同一 sha256 NASM/C 出力。CFG / 関数境界 / 命令列すべて含めて完全決定論。
- Native ELF round-trip出力 NASM を nasm + ld で再 assemble、出力 C を gcc -nostdlib で compile、2 系統の native ELF を実行して原 binary と stdout 完全一致。シミュレーションでなく実機検証。
- Mutation 検出.text 1 bit 反転で disasm が必ず差分を出す。Linux 25 sample × 5 trial = 125/125 + Windows 19 sample × 5 trial = 95/95、改ざん即発覚。
- 決定論同一 ELF を 2 回 disasm + emit → byte-equal を毎 sample で確認。並列実行・GPU 環境でも結果がブレない。
- Slot IR audit関数 = Slot ノード、call graph も保持して JSON で外部に永続化可能。SBOM / 監査 DB との結合点。
- Build-time LLMLLM は decoder rule の構築段階のみ。ランタイムは決定論ルールベース、銀行・防衛 audit 要件に整合。
サポート命令カバレッジ (Linux/Windows 共通、整数 + memory subset 約 37 種)
| データ移動 | mov reg/mem, imm/reg (B8+r / 89 /r / 8B /r / C7 /0 / 88 /r、64-bit + 32-bit 両方) / mov r32, imm32 (B8+r、no REX.W) / movzx r32/64, r/m8 (0F B6 /r、zero-extend) / movsx r32/64, r/m8 (0F BE /r、sign-extend) / lea r64, m (8D /r、SIB / [reg+disp] / [rip+disp] 全形態) / nop (90) / leave (C9) |
|---|---|
| 算術 | add r/m, r (01 /r、reg + mem dst、64/32-bit) / add r/m, imm8 (83 /0、reg + mem dst、64/32-bit) / add rax, imm32 (REX.W 05 imm32) / sub r/m, r (29 /r、64/32-bit) / sub r/m, imm8 (83 /5) / imul r, r/m (REX.W 0F AF、reg + mem src) + 32-bit (no REX.W) / imul r/m64 1-op (REX.W F7 /5、RDX:RAX = signed 128-bit product) / idiv r/m (F7 /7、64/32-bit) / cqo (REX.W 99、sign-extend rax→rdx:rax) / cdqe (REX.W 98、sign-extend eax→rax) / cdq (99 no REX.W、sign-extend eax→edx:eax) / movsxd r64, r/m32 (REX.W 63 /r、32→64 sign-extend) |
| 論理 | and / or / xor r/m64, r64 (21/r、09/r、31 /r、reg + mem dst) / and r/m, imm8 (83 /4)、or r/m, imm8 (83 /1)、idiom xor reg, reg はゼロ初期化として認識 |
| ビットシフト | shl / shr / sar r/m, imm8 (C1 /4/5/7 imm8、64/32-bit) / shl / shr / sar r/m, 1 (D1 /N、64/32-bit) |
| 比較・test | cmp r/m64, r64 (39 /r、64/32-bit) / cmp r/m, imm8 (83 /7、reg + mem dst) / test r/m8, r8 (84 /r) / test r/m32/64, r32/64 (85 /r) |
| 分岐 | Jcc rel8 (70-7F、je/jne/jge/jg/jl/jle/jb/jae/jbe/ja/js/jns/...) / Jcc rel32 (0F 80-8F) / jmp rel8/32 (EB/E9) / loop rel8 (E2) |
| 呼出 | call rel32 (E8) / ret (C3) / push/pop r64 (50-5F) / push imm (6A/68) |
| システム | Linux: syscall (0F 05) — sys_write (rax=1) / sys_exit (rax=60) を heuristic 認識。Windows: IAT 経由 indirect call (mov rax, qword [rip+iat]; call rax) を peephole で call_iat <FUNC> に折り畳み、Win64 ABI (rcx/rdx/r8/r9 + [rsp+0x20]) で WinAPI 直接呼び出し |
| 制御フロー (indirect) | call r/m64 (FF /2 reg + mem) / jmp r/m64 (FF /4 reg + mem) / inc/dec/push r/m64 (FF /0/1/6) / leave (C9) / multi-byte NOP (0F 1F /0) |
| メモリオペランド | [reg] / [reg+disp8] / [reg+disp32] / [rip+disp32] / [base+index*scale+disp] (SIB byte、scale=1/2/4/8、REX.X による index 拡張) — gcc -O0 が頻出する [rbp-disp] ローカル変数アクセスと [rax*8+disp] 配列インデックス、Win64 shadow space [rsp+0x20] 全網羅 |
次フェーズで printf / malloc / PLT/GOT 動的リンク、SSE2 / SSE4 (XMM レジスタ + 浮動小数点)、3-op imul r64, r/m64, imm32 (0x69 /r、-O2 以降で頻出)、movabs r64, imm64 (REX.W B8+r imm64、64-bit 絶対値) 等の対応を順次拡張予定。本ページの Linux ELF 25 sample × 8 軸 = 200/200 + Windows PE32+ 19 sample × 8 軸 = 152/152 = 合算 352/352 PASS 達成は 2026-05-19 時点。
License モデル
| 課金対象 | WASM/WASI converter ツール (開発者側) |
|---|---|
| 非課金 | 変換結果の NASM / C ソース (顧客資産、永久無償デプロイ) |
| 方式 | Ed25519 署名 144B license + 3-hop air-gap activation (金融・防衛 audit 対応) |
| 並列化 (PSDP) | 本製品には含まれません。SlimeNENC 配下の独立 SKU として PSDP を別途。 |
関連資料
- 技術解説SlimeNENC Technical Overview (逆方向 ASM/C 章を準備中)
- 出願明細特願 2026-046620 v15b の請求項 11 / 14d で COBOL / MUMPS / PL/I / RPG / アセンブラ / native binary 逆方向等のレガシー方言処理を明示射程化
- 兄弟製品 (forward 系対)SlimeASM (HLASM + Win x64 MASM forward) と対 — forward + reverse の双方向で SlimeNENC ファミリーが native コード領域を完全カバー
- 兄弟製品 (Slot IR 共有)SlimeCOBOL / SlimePL/I / SlimeRPG / SlimeMUMPS と Slot IR (Core64+Ext32 固定 bit) を共有
- ベンチマークS9 bench harness (8 軸 correctness)、Linux
asm_rev_to/s9_bench/bench.py+ Windowspe_rev_to/s9_bench/bench.pyで合算 44 sample × 8 軸 = 352/352 自動回帰 (Linux 25 + Windows 19、~37 種 opcode、Slot IR 統一 schema)
逆変換 PoC・資料請求 SlimeNENC ファミリーへ戻る SlimeASM (forward 対) を見る SlimeCOBOL を見る
