はじめに
メインフレーム移行というと、まず話題になるのはCOBOLです。
しかし、実際の基幹システム移行では、COBOLだけをJava化しても終わらないケースがあります。
理由のひとつが、業務システムの奥に残っている アセンブラ資産 です。
特にIBM z/OS系の環境では、COBOL本体の周辺に、次のようなアセンブラコードが残っていることがあります。
- CPU時間を食うhot-loop
- packed decimal演算
- OSマクロ呼び出し
- ファイルI/O
- SVC / GETMAIN / FREEMAIN
- 例外・異常終了系の制御
- DCB / EODAD などのz/OS固有構造
表面上はCOBOLシステムに見えても、性能やI/Oや特殊処理の中核にHLASMが残っていると、移行プロジェクトはそこで止まります。
この問題に対する取り組みとして、Javatelでは SlimeASM を開発しています。
公式ページ:
SlimeASM — z/Architecture HLASM + x64 MASM → Java bit-exact 変換
SlimeASMとは
SlimeASMは、アセンブラ資産をJavaへ変換するためのSlimeNENCファミリー製品です。
対象は大きく2系統です。
- z/Architecture HLASM
- Windows x64 MASM / ml64
目的は、アセンブラを単にJava風に書き換えることではありません。
中心にあるのは、
アセンブラの実行意味を、Java上で決定論的に再現する
という考え方です。
そのため、SlimeASMではPC-based switch dispatch方式を用いて、アセンブラの制御フローをJavaの switch ベースの実行モデルへ写像します。
概念的には、次のような形です。
ASM source
|
v
S1: ASM FST / dialect parser
|
v
S2-S5: SlimeNENC共通中間表現
|
v
S6: Java emitter
|
v
S7-S9: audit / determinism / regression
SlimeNENCファミリーでは、S2 Slot符号化、S3 Π_R正規化、S4 SOLOT、S5受理関数、S7監査チェーン、S8 Mini-PSV、S9 5軸benchを共有し、S1 parserとS6 emitterのみを言語固有にします。
つまり、SlimeASMは単独の変換器でありながら、SlimeCOBOLやSlimeJCLなどと同じ基盤上で動く設計です。
なぜアセンブラが移行を止めるのか
COBOL移行では、LOCベースで見るとアセンブラは小さく見えることがあります。
しかし、問題は行数ではありません。
アセンブラは、しばしば次のような場所に残ります。
全体LOCの一部
|
+-- 性能クリティカルなhot-loop
+-- packed decimal演算
+-- OS依存I/O
+-- 例外・終了処理
+-- COBOLから呼ばれる外部ルーチン
つまり、コード量は少なくても、システムの意味や性能の要所にいます。
この部分を人手でC/C++やJavaに書き直すと、次の問題が起こります。
- 変換結果が属人化する
- 元の挙動との差分を検証しにくい
- packed decimalや浮動小数点の再現が難しい
- OSマクロの意味を落としやすい
- 監査証跡を残しにくい
- 1行単位の個別リライトになり、コストが膨らむ
SlimeASMは、この「最後に残るASM部分」を、決定論的変換と監査チェーンで閉じることを狙っています。
z/Architecture HLASMの対応範囲
公式ページによると、z/Architecture HLASM側は Phase A → C-3.7 まで進んでおり、49 sample × S9全5軸 = 245/245 PASS とされています。
対応範囲はかなり広く、以下のような命令群が含まれます。
整数命令
L / LR / LA / LH / LM
ST / STH / STM
A / AR / AH
S / SR / SH
M / MR / MH
D / DR
C / CR / CH / CL / CLR / CLC
B / BR / BC / BE / BNE / BL / BH
BCT / BCTR / BAS / BAL
MVC / MVI / XC / OC / NC
10進演算
AP / SP / MP / DP / ZAP / CP / CVB / CVD
IBM mainframeの4-bit packed decimalをJava側で再現します。
Javaでは、10進演算の意味を保つために BigDecimal バッキングを利用します。
HFP
IBM hexadecimal floating pointにも対応します。
LE / LD / AE / AD / SE / SD / ME / MD / DE / DD
IBM 4-bit指数のhex floatとIEEE 754の間を、bit-exactに変換する設計です。
OSマクロshim
z/OS固有のマクロも、Java / POSIX shimへ写像します。
GETMAIN / FREEMAIN / ABEND / SVC / RETURN
OPEN / CLOSE / GET / PUT / READ / WRITE / DCB
このあたりが、単純な命令変換では済まない重要部分です。
変換・編集命令
PACK / UNPK
TR / TRT
ED / EDMK
特に TR / TRT は256-byte任意テーブルを扱うため、文字変換や検査処理の再現に重要です。
SIMD / Vector
z/ArchitectureのVectorレジスタにも対応しています。
VL / VST / VA / VS / VLR / VLEG / VSTEG
VC / VCE / VPERM / VSEL
制御・アドレスモード
EX
SAR / EAR / CPYA
SAM24 / SAM31 / SAM64
BSM / BASSM
EX、いわゆるExecute trickや、AMODE切替も対象に入っています。
x64 MASM / ml64の対応範囲
SlimeASMはz/Architectureだけでなく、Windows x64 MASMにも対応しています。
公式ページでは、x64 MASM側は Phase A、5 sample × S9全5軸 = 25/25 PASS とされています。
対象は、まず整数hot-loopです。
mov / lea / xchg / push / pop
add / sub / inc / dec
imul / idiv / neg
and / or / xor / not
shl / shr / sar
cmp / test
jmp / je / jne / jl / jle / jg / jge
loop / call / ret
レジスタは、以下に対応します。
RAX / RCX / RDX / RBX
RSP / RBP / RSI / RDI
R8 ... R15
さらに、eax、ax、al、r8d、r8w、r8b などのサブレジスタも扱います。
x64では、32-bit書き込みはゼロ拡張され、16-bit / 8-bit書き込みでは上位ビットが保持されます。
このような細かいレジスタ意味論を落とすと、変換後のJavaは見た目が正しくても動作がズレます。
SlimeASMでは、この種の挙動もbit-exact再現の対象にしています。
変換例:z/Architecture HLASMのecho loop
公式ページにある例では、DCB EODADを使ってstdinのEOFを捕捉し、出力へ転写するecho loopが示されています。
* SlimeASM sample 49 — echo until EOF using DCB EODAD= branch.
ECHOL CSECT
OPEN (INDCB,(INPUT),OUTDCB,(OUTPUT))
LOOP GET INDCB,RECBUF
PUT OUTDCB,RECBUF
B LOOP
EOFRTN DS 0H
CLOSE (INDCB,,OUTDCB)
WTO 'ECHO_LOOP_OK'
BR 14
INDCB DCB DDNAME=DDIN,DSORG=PS,MACRF=GM,EODAD=EOFRTN
OUTDCB DCB DDNAME=DDOUT,DSORG=PS,MACRF=PM
RECBUF DS CL80
END ECHOL
ここで重要なのは、EODAD=EOFRTN です。
HLASMでは、EOF時に指定されたラベルへ制御が飛びます。
SlimeASMのS6 emitterは、DCB属性を読み取り、GET 命令のEOFパスを EOFRTN ラベルへの直接PCジャンプとしてJavaへ翻訳します。
概念的には、次のような制御になります。
GET INDCB,RECBUF
|
+-- read success -> PUT -> LOOP
|
+-- EOF -> pc = EOFRTN
単に readLine() を呼ぶだけではなく、z/OSマクロの制御意味をJava上で再現する点がポイントです。
変換例:x64 MASMの整数hot-loop
x64 MASM側では、loop 命令を含む整数加算ループの例があります。
xor rax, rax
mov rcx, 5
sum_loop:
add rax, rcx
loop sum_loop
これは、5 + 4 + 3 + 2 + 1 を計算して rax = 15 にする典型的なhot-loopです。
SlimeASMでは、このような制御フローをPC-based switch dispatchへ変換します。
概念的には以下のようなJavaになります。
case 1:
R[1] = 5L; // mov rcx, 5
pc++;
break;
case 2:
R[0] = R[0] + R[1]; // add rax, rcx
ZF = (R[0] == 0) ? 1 : 0;
SF = (R[0] < 0) ? 1 : 0;
pc++;
break;
case 3:
R[1] = R[1] - 1; // loop sum_loop
pc = (R[1] != 0) ? 2 : pc + 1;
break;
この方式では、元アセンブラのラベル、分岐、条件フラグ、レジスタ更新をJavaの状態機械として再現できます。
5軸benchによる検証
SlimeASMでは、Java出力をcanonical runtimeとして扱い、S9 benchで検証します。
公式ページでは、以下のような5軸が示されています。
1. dialect
2. token-recover
3. mutation
4. determinism
5. java round-trip
特に重要なのは、次の3点です。
1. 決定論
同じ .s / .asm 入力から、同じJavaが生成されます。
これは、変換器の出力が揺れないということです。
same input
|
+-- emit #1 -> Java A
+-- emit #2 -> Java A
2. Java round-trip
生成Javaを javac でコンパイルし、java で実行し、stdoutをexpectedとdiffします。
つまり、生成物が見た目だけでなく、実行結果としても検証されます。
3. mutation検出
任意位置にSOH、つまり 0x01 を注入し、tokenizerがrejectできるかを確認します。
これは、破損入力や改ざん入力を検出するための重要なテストです。
audit chainによる監査証跡
金融・防衛・公共系の移行では、「変換できた」だけでは足りません。
後から次のことを説明できる必要があります。
- どの入力から生成されたのか
- どの変換器で生成されたのか
- 出力Javaは改ざんされていないか
- 同じ入力から再生成したとき一致するか
- どのテストでPASSしたか
SlimeASMは、SlimeNENC共通基盤のS7 audit chainと統合可能です。
概念的には、append-onlyなSHA-256 chainです。
record_1 -> hash_1
record_2 -> hash_2 = H(hash_1 + record_2)
record_3 -> hash_3 = H(hash_2 + record_3)
...
途中のrecord blobが1 byteでも変更されると、後続のhashが一致しなくなります。
これにより、変換プロセスの追跡可能性と改ざん検出を確保します。
LLMを本番変換経路に入れない理由
SlimeASMの設計で重要なのは、LLMをランタイム変換の中心に置かないことです。
LLMは、仕様整理、命令意味の整理、テストケース設計、説明文生成などには使えます。
しかし、本番の変換経路は決定論的なルールベースで動きます。
LLM
|
+-- 調査・仕様整理・テスト補助
|
v
deterministic converter
|
v
same ASM -> same Java
アセンブラ変換では、1 bitの違いが結果を壊します。
そのため、本番変換で出力が揺れる仕組みは使いにくい。
SlimeASMは、LLMの便利さを活用しつつ、最終成果物は決定論的に固定する方針です。
SlimeNENCファミリーでの位置付け
SlimeASMは、SlimeNENCファミリーの中で、COBOL移行を完走させるための最後のピースに近い位置付けです。
特にIBM z/OS系の移行では、次の3点セットが重要になります。
COBOL本体 -> SlimeCOBOL
JCL制御 -> SlimeJCL
ASM hot-loop -> SlimeASM
COBOLだけ移しても、JCLが残ればバッチが動きません。
JCLまで移しても、HLASM hot-loopやOSマクロが残れば、業務ロジックや性能クリティカル部分が移りません。
その意味で、SlimeASMは「COBOL移行ツール」ではなく、レガシー基幹システム移行全体の詰まりどころを埋める技術です。
ライセンスモデルの考え方
公式ページでは、ライセンスモデルについても特徴的な設計が示されています。
課金対象:
WASM/WASI converter tool
非課金:
変換結果のJavaソース
つまり、変換器に課金し、生成されたJavaソースは顧客資産として永久無償デプロイ可能、というモデルです。
また、金融・防衛系のauditに対応するため、Ed25519署名つきライセンスやair-gap activationも想定されています。
まとめ
SlimeASMは、z/Architecture HLASMとWindows x64 MASMをJavaへ変換するための決定論的トランスパイラです。
特徴をまとめると、以下の通りです。
- z/Architecture HLASM → Java
- Windows x64 MASM / ml64 → Java
- PC-based switch dispatchによる制御フロー再現
- packed decimal / HFP / vector / EX / TR/TRT / ED / DCB EODADなどに対応
- x64レジスタ・サブレジスタ意味論をbit-exactに再現
- Java round-tripを含むS9 5軸bench
- mutation検出
- determinism検証
- audit chainによる監査証跡
- LLMを本番変換経路に入れない決定論的設計
- SlimeCOBOL + SlimeJCL + SlimeASMによる移行三点セット
COBOL移行が最後に止まる理由は、COBOLそのものではなく、その奥にあるアセンブラ資産かもしれません。
SlimeASMは、その「最後に残るASM」を、Javaへ検証可能な形で移すためのアプローチです。