【入門編】ABS関数の算術演算と符号ビットの操作 – PL/Iの基本構文とデータ制御実践ガイド

こんにちは!メインフレームの世界へようこそ。
JavaやCOBOLといったモダン、あるいはビジネス標準の言語を経験されてきた方にとって、IBMメインフレームの「PL/I(ピーエルワン)」という名前は、少し古めかしく、どこか近寄りがたいダンジョンのように感じられるかもしれませんね。

「なんだか記号だらけで難しそう…」
「COBOLみたいに英語っぽくないし、C言語に似ているようで違う…」

そんな風に身構えてしまうお気持ち、とてもよく分かります。でも、安心してくださいね。一つひとつの仕様を紐解いていけば、PL/Iは非常に合理的で、私たちの意図を素直に実行してくれる可愛い相棒のような存在です。

今回は、そんなPL/Iの懐の深さと、メインフレームならではの「マシン語直結の泥臭い魅力」が味わえるテーマ「ABS(絶対値)関数の裏側と、符号ビットの秘密」について、おしゃべりするようにお伝えしていきたいと思います。

—

1. PL/Iの優しい世界:識別子と「予約語がない」という衝撃

JavaやC言語を触ったことがある方なら、「あ、それって予約語(キーワード)だから変数名に使えないよ!」とコンパイラに怒られた経験が一度はあるはずです。`if` とか `for` とか `int` とかですね。

ところが、PL/Iの初期の設計思想はこうでした。
「プログラマがどんな名前をつけようと、文脈から判断してコンパイルしてあげるよ!」

これがどういうことかというと、PL/Iには厳密な意味での予約語というものが存在しません(厳密には一部例外はありますが、基本概念として)。
例えば、極端な話ですが、こんな変数宣言もできちゃいます。

1
DCL IF FIXED BIN(31); / 変数名に ‘IF’ を使っちゃう暴挙 /
DCL THEN FLOAT; / 変数名に ‘THEN’ を使っちゃう暴挙 /

「えっ、そんなことしたら処理系がパニックを起こすのでは…?」と思いますよね。でも、PL/Iのコンパイラは優秀です。前後の文脈(ここで `IF` が来たら条件分岐の命令だな、ここでは変数名だな)を驚異的な解析力で読み解きます。

とはいえ、実務の現場でこんな名前をつけると、後からコードを読む同僚(あるいは将来のあなた自身)が発狂してしまいますので、マネしないでくださいね(笑)。でも、「名前の縛りが緩くて、プログラマの自由を尊重してくれる言語なんだな」と知るだけでも、少し親しみが湧いてきませんか?

—

2. メインフレームの心臓部:FIXED BINARYとデータ型のお話

さて、今回の本丸である「数値のデータ型」についてお話ししましょう。
PL/Iで数値を扱うとき、私たちは主に以下の2つをよく使います。

  • FIXED BINARY(固定小数点二進数): いわゆるJavaの `int` や `long`、COBOLの `COMP`(コンピュテーション項目)に相当します。計算が速く、メインフレームのCPUが一番得意とする形です。
  • FLOAT(浮動小数点数): 科学技術計算などで使われる、大きな数や小さな数を表す型ですね。

今回は、この中の FIXED BINARY、特に 31ビットのフルワード(`FIXED BIN(31)`)にスポットを当ててみましょう。メインフレームの文字や数字の裏側では、2進数の世界が広がっています。

—

3. ABS関数が織りなす魔法:マイナスをプラスにするということ

プログラムを作っていると、「マイナスの値が出てきたら、符号をとってプラス(絶対値)にしたい!」という場面によく遭遇しますよね。そんなとき、私たちは迷わず `ABS` 関数を使います。

1
DCL W_ORIGINAL FIXED BIN(31) INIT(-12345);
DCL W_ABS FIXED BIN(31);

W_ABS = ABS(W_ORIGINAL); / -12345 を 12345 に変換する /

たったこれだけ。とても簡単で、他の言語と同じように直感的に使えますよね。「なんだ、ABSってただの関数じゃないか」と思いましたか?
しかし、ここからがメインフレーム、そしてPL/Iの真骨頂です。「この絶対値を求める処理、ハードウェア(CPU)レベルではどう動いているの?」というお話を少しだけ覗いてみましょう。

符号ビットと、IBM汎用機の「LPR命令」

コンピュータの世界では、マイナスを表現するために「2の補数」という仕組みを使います。31ビットのFIXED BINARYであれば、一番左側のビット(最上位ビット)が「符号ビット」になります。

  • 符号ビットが `0` ならば プラス
  • 符号ビットが `1` ならば マイナス

もし、あなたが書いたPL/Iのコードで `ABS(W_ORIGINAL)` が実行されるとき、IBMのメインフレーム(Zアーキテクチャ)のCPU内部では、何が行われているでしょうか?

コンパイラは非常に賢いので、ただ単純に「マイナスだったら-1を掛ける」なんていう非効率なことはしません。CPUが持つ専用の機械語命令、例えば LPR(Load Positive Register:レジスタに絶対値をロードする)命令 などをバックグラウンドで発動させています。

LPR命令の動きは実にシンプルかつ高速です。
1. レジスタに数値を読み込む。
2. 強制的に符号ビットをクリア(強制的に `0` に書き換える)、あるいは算術的に正の値に整える。
3. 一瞬で絶対値が完成する!

このように、PL/Iの `ABS` 関数というハイレベルな記述の背後には、メインフレームのハードウェアの特性(符号ビットの直接操作や高速レジスタ演算)がダイレクトに結びついているのです。基幹システムのバッチ処理で、何千万件もの膨大なデータを一瞬で処理できる秘密は、こういうところにあるんですね。

—

4. 実務で役立つ!PL/Iコード例と安全な設計のコツ

それでは最後に、実際のマイグレーションやバッチ改修の現場を想定した、実用的なPL/Iのコードサンプルを見てみましょう。
「型違いによる暗黙の型変換の罠」や「オーバーフロー」を防ぐための、ちょっとしたコツも添えておきますね。

1
——————————————————————

  • プログラム名: ZABS01PL
  • 概要 : FIXED BINARYのABS演算と符号ビット操作のサンプル

——————————————————————
ZABS01PL: PROC OPTIONS(MAIN);

/ 変数宣言ブロック /
/ 31ビットの固定小数点二進数を定義します(COBOLのCOMPにあたります) /
DCL WS_INPUT_VAL FIXED BIN(31) INIT(-2147483648); / 最小値の例 /
DCL WS_ABS_VAL FIXED BIN(31);
DCL WS_MSG_AREA CHAR(80);

/ 1. 通常のABS関数の利用 /
/ 注意: FIXED BIN(31) の表現できる正の最大値は 2147483647 です。 /
/ 最も小さな負の値(-2147483648)をABSに渡すと、オーバーフローが起きるため /
/ 実務では入力値の範囲チェックが不可欠です! /

IF WS_INPUT_VAL = -2147483648 THEN DO;
PUT SKIP LIST(‘【警告】許容範囲を超えるオーバーフロー値です。’);
/ 必要に応じたエラー処理をここに記述します /
END;
ELSE DO;
/ ここでコンパイラが効率的なマシン語(LPR命令など)を生成します /
WS_ABS_VAL = ABS(WS_INPUT_VAL);

/ 結果を出力 /
PUT SKIP EDIT
(‘変換前:’, WS_INPUT_VAL, ‘ / 変換後(ABS):’, WS_ABS_VAL)
(A(8), F(12), A(15), F(12));
END;

RETURN;

END ZABS01PL;

💡 ここだけは押さえておきたい実務の知恵

サンプルコードの中でも少し触れましたが、`FIXED BIN(31)` の世界では、表現できる数値の範囲が決まっています($-2^{31}$ から $2^{31}-1$ まで)。
もし、マイナスの極限値(`-2147483648`)に対してそのまま `ABS` をかけると、対応するプラスの数値(`2147483648`)は31ビットの枠に収まりきらないため、残酷なオーバーフロー(桁あふれ)を引き起こしてしまいます。

レガシーシステムの移行や保守の現場で「なぜか突然ABEND(異常終了)するんだけど…」というトラブルの原因をたどると、こうしたデータ型の境界値でABS演算を行い、ハードウェアが悲鳴を上げているケースに出くわすことがよくあります。
「ABSを使うときは、値の範囲(境界値)に気を配る」――これさえ覚えておけば、もう怖いものはありません!

—

おわりに

いかがでしたでしょうか?
「識別子に予約語がないという自由奔放さ」や、「ABS関数の裏側でCPUの符号ビットクリア(LPR命令)が火を噴いていること」など、PL/Iとメインフレームの世界が少し身近に感じられたのではないでしょうか。

レガシーシステムの世界は、一見すると古臭く取っつきにくく見えますが、突き詰めていくと「いかにハードウェアの性能を限界まで引き出し、データを高速かつ安全に処理するか」という先人たちの知恵と工夫が詰まった、非常にロマンチックな世界です。

「難しそう」を「なんだ、こういうことか!」に変えながら、一緒に楽しくメインフレームのスキルを磨いていきましょうね。あなたのレガシー移行やバッチ開発の旅が、実り多いものになりますように!

タイトルとURLをコピーしました