1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

COBOL移行を最後に止める「アセンブラ残骸」問題 ― SlimeASMの技術概要

1
Posted at

はじめに

メインフレーム移行というと、まず話題になるのは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

さらに、eaxaxalr8dr8wr8b などのサブレジスタも扱います。

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へ検証可能な形で移すためのアプローチです。


関連リンク

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?