表示調整
閉じる
挿絵表示切替ボタン
▼配色
▼行間
▼文字サイズ
▼メニューバー
×閉じる

ブックマークに追加しました

設定
0/400
設定を保存しました
エラーが発生しました
※文字以内
ブックマークを解除しました。

エラーが発生しました。

エラーの原因がわからない場合はヘルプセンターをご確認ください。

ブックマーク機能を使うにはログインしてください。
24/37

エピ15 算術演算子の分岐処理を確かめよう


 ***


 エピ15 算術演算子の分岐処理を確かめよう


 ***


 数式、...例えば 0+1 のような、...を入力すると 2251h をコールして処理をします。その処理中の話ですが。数値 0 を評価したら、次が算術演算子の "+" だと 22D4h をコールするようです。

 それで 22D4h では算術演算子の処理をしているに違いないと、エピ14では推測しました。


 その通りなのか確認します。


 ***


 早速に。22D4h〜22F6h のコードを見ます。


  _22D4h:

   [4644h] += 0005h # 数値ワーク +5

   push BC # BC=226Ah +++ BC

   push [25ADh+(A-B0h)*2] # A=BCh +++ 分岐先の番地

   push 22F7h # +++ 22F7h

   push DE # DE=22B1h +++ DE

   exx

   if D==00h: ret # D=00h, RET to 22B1h

  _22F4h:

   jp 1399h # err-msg MISMATCH


 数値ワークを +5 して、PUSH を4回して、RET しているのですね。


 22D4h をコールする前には 0+1 の 0 を評価していて、その結果が数値ワークに残っています。それで次の値を評価するために数値ワークを +5 するのです。エピ11で見た通りです。


 それから4回の PUSH。


 BC と DE の値はコール元で設定しています。


   1) 21FFh: BC = 2202h, DE = 2250h

   2) 2251h: BC = 226Ah, DE = 22B1h

   3) 22B2h: BC = 22B5h, DE = 22C4h

   4) 22C5h: BC = 22C8h, DE = 231Ch


 A の値は算術演算子の中間コードです。25ADh 番地にあるジャンプテーブルを参照して PUSH しています。中間コードの分岐先の番地なのでしょう。

 BC と DE、それと 227Fh という謎の値は RET するときに出てきます。


 2251h からの処理の流れを整理すると。


  ・2) のルーチンは 3) をコールして、3) は 4) をコールして、4) は 231Dh をコールして、231Dh で数値 0 を評価して数値ワークに設定して、リターンする。

  ・2) のルーチンに戻ってきたら、A の値を調べて中間コード BCh("+")だったら、BC=226Ah, DE=22B1h を設定して 22D4h にジャンプする。

  ・22D4h では、push DE して RET する。つまり、DE=22B1h へジャンプする。

  ・22B1h 番地では inc HL して 3) に続き、4)、231Dh と行って、1 を評価して数値ワークに設定して、リターンすると、...スタックには 22F7h が入っていて、22F7h にジャンプすることになる。

  ・スタックには、分岐先の番地と DE=226Ah の2つが残っていることを覚えておいて!


 ふむふむ。


 *


 では 22F7h〜2310h のコードを見ます。

 

  _22F7h:

   if D!=00h: jr 22F4h # D=00h

   pop IY # IY=2D0Eh --- 分岐先の番地

   push HL # HL=445Eh +++ HL

   push 2314h # +++ 2314h

   HL = [4644h] # HL=481Dh

   [4644h] += FFFBh # 数値ワーク -5

   DE = [4644h] # DE=4818h

   JP [IY] # IY=2D0Eh ジャンプ!


 22F7h のルーチンでは、pop IY してスタックから分岐先の番地を取り出して、PUSH を2回する。この時点でスタックには(22D4h で PUSH した)BC=226Ah と、HL と 2314h が入っている。


 それから数値ワークを -5 する。HL に 1 を評価した数値の番地、DE には 0 を評価した数値の番地を設定する。


 そして、IY の番地にジャンプする。ここが中間コード BCh の分岐先だ!


 *


 算術演算子の中間コードでジャンプテーブルを参照して分岐先を得て、演算子の左辺と右辺が入った番地を DE と HL に設定して、分岐先に飛んで行きます。


 中間コード BCh('+')なら 2D0Eh 番地に行くはずです。DE と HL から2つの数値を読み出して、加算して、結果を数値ワーク [4644h] に転送して、リターンするのでしょう。


 すると、スタックには 2314h が入っているので、そこに行きます。


 *


 最後のコードです。2314h〜231Bh を見ます。


  _2314:

   pop HL # HL=445Eh

   BC = 0005h

   DE = 0000h

   A = [HL] # A=0Dh

   ret # RET to 226Ah


 スタックから HL を POP して、BC,DE,A を設定して、リターンします。


 ...、ってスタックには(22D4h で PUSH した)BC=226Ah が残っているので、そこに行くのです。


 226Ah は 2251h のルーチンの中で、A の値を判定するところです。0+1 の場合は終端 0Dh に来ているので、リターンします。


 ... 2251h をコールした元に戻ります。LET 命令文なら 1B34h 番地ですね。


 *


 予定調和的な結論ですけど。綺麗に収まりました。


 エピ12で出てきた 05 00 00 00 は 2314h が設定した値か。...、ちょっと懐かしいです。


 ***


 22D4h のルーチンで参照したジャンプテーブルを確認します。


   push [25ADh+(A-B0h)*2]


 25ADh 番地からのデータですね。


   25AD: 3465h # >< B0

   25AF: 3465h # <> B1

   25B1: 348Ah # =< B2

   25B3: 348Ah # <= B3

   25B5: 348Eh # => B4

   25B7: 348Eh # >= B5

   25B9: 3482h # = B6

   25BB: 3476h # > B7

   25BD: 347Ah # < B8


   25BF: 268Ah # AND B9

   25C1: 268Dh # OR BA

   25C3: 268Fh # NOT BB


   25C5: 2D0Eh # + BC

   25C7: 2D0Bh # - BD

   25C9: 2E08h # * BE

   25CB: 2ED6h # / BF

   25CD: 3A5Ah # ^ C0 <-- CF


 A=BCh なら 25ADh + (BCh-B0h)*2 = 25C5h ... 分岐先は 2D0Eh で間違いないです。


 *


 余談になりますが。


 ジャンプテーブルに AND, OR, NOT があるので分岐先のコードを見に行ったら、


   268A: jp 138Ah # err-msg SYNTAX ERROR

   268D: jr 268Ah # = err-msg

   268F: jr 268Ah # = err-msg


 でした。なんなのー


 *


 余談になりますが(その2)


 べき乗 ^ の中間コードは CFh なのですが、4) 22C5h の中で C0h に変換しています。中間コードが B0h〜BFh まで埋まってしまったので苦肉の策ですか。


 ところで >< と <> の分岐先は同じですね。不等号が2種類あるのはBASICだからかな。...、これを削れば、...。あるいは実態がない AND, OR, NOT はキーワードから外したらどうかな?


 ***

 **

 *


 スタックに複数個のリターン番地を設定(PUSH)して、サブルーチン(をコールせず)へジャンプする。


 サブルーチンはコール元が偽装されているかは知るすべもなくリターンして、設定された番地に行く。そこがまたサブルーチンだったらリターンして、設定された次の番地に行く。


 これを何個でもつなげることができる。スタック領域の範囲内でね。


 リターン番地はサブルーチンの先頭である必要はなくて、RET の数ステップ前で良い。RET の直前付近で、都合の良いシステムコールをしているコードがあればラッキーだ。


 するとプログラム領域のコード(の断片)を繋ぎ合わせて、所望のプログラムを得ることができる。書換えが禁止されている領域であってもだ。


 ...、そんなことを連想させる技法が 2251h に入っていました。


 *


 この技法は2000年代に実用(悪用?)されて一部の業界で話題になっていたようです。


 SP5030は1980年か1981年頃のリリースで今から45年前。


 温故知新と言う言葉を思い出す。工学分野での考古学かな?


 電子計算機において、...あるいはパソコンか、CPUを組み込んだ機器、...スマホ等において...、当り前で、当然だったこと、...を現在の開発者が知っていることは大切よね。


 ***

 **

 *


 いやはや(死語?)


 コールしたら RET で戻ってこないし、一方でどこからコールされるか不明なコードがゴロゴロしていて悩みましたよ。


 PUSH と POP の数が合わないと気付いたのが最初のヒントでした。機械語は気難しいです。


 ***


 間違いの指摘とか疑問とか、ご意見・ご感想とかありましたら、どうぞ感想欄に!


 ***

2026.3.10 誤記訂正と微推敲

2026.3.11 推敲

2026.4.17 微推敲

2026.5.4 コピペミスを修正。痛恨。


評価をするにはログインしてください。
ブックマークに追加
ブックマーク機能を使うにはログインしてください。
― 新着の感想 ―
このエピソードに感想はまだ書かれていません。
感想一覧
+注意+

特に記載なき場合、掲載されている作品はすべてフィクションであり実在の人物・団体等とは一切関係ありません。
特に記載なき場合、掲載されている作品の著作権は作者にあります(一部作品除く)。
作者以外の方による作品の引用を超える無断転載は禁止しており、行った場合、著作権法の違反となります。

↑ページトップへ