/var/log/hdk.log

2021 年 5 月上旬

prev, this, next


01 (土)

%1 どようび

なんか日曜日な気がする土曜日。 夕方頃雷雨だった。 雷が少し落ち着いたか、ってタイミングで雨ザーザーの中、カッパを着て弁当を買いに行ったけど、帰りにまたピカピカやり始めてなかなか... 近くはなかったけど稲妻が視界に入った。

『るろうに剣心』のアニメ版 25 話までを見たが、なんか、ここまででも違うバトルが何度もあって、実写映画の感覚からするとちょっと予想外だった。 地面が割れるってまぁ実写映画じゃ困るやつかも知れんが... 仲間のけんか屋さんとの戦いもあったし、海賊や、蒸気機関車の話も。 しかも、海の中を通る鉄道って、最近品川あたりで遺構が見つかったっていう高輪築堤じゃないか。 汽車を止めて船から襲うって設定は、海の中を通る鉄道だからこそなので、おもしろいと思う。 走行中の車両を切り離すのはブレーキどうなるの? って思っちゃうけど、時代を考えると、貫通ブレーキじゃなくてつまりブレーキ管が引き回されてはいなかったようだ。 というか、当時はブレーキが付いた車両に制動手という乗務員がいて、ブレーキは機関車の他は一部車両に付いていただけだったようだ。 今の列車は、全車両にブレーキが付いている上、空気圧なり電気信号なりでつながっていて、切れると自動的にブレーキがかかるようになっているから、止まらないように切り離すのは難しいだろう。

例の塗りつぶしアルゴリズムを考え、実装してみたが、まだ何かおかしい。 とりあえず無限ループになると動作確認が大変だったので、塗った色に引っ掛かったらログを残してそこは壁扱いにすることで無限ループを避けて試しているんだけど、なーんか、うまくいかないなぁ。 なんて難しいんだ、塗りつぶしってやつは。

2021/05/01 のコメントを読む・書く


02 (日)

%1 にちようび

のんびり。

このところ考えていた塗りつぶしアルゴリズムを実装したのがこちら: 20210502-canvas1.html

マウスでぐりっと線を引いて塗りつぶしを試せる。 デフォルトは低速モード、これはインターバルタイマーを使ってあえてゆっくり塗りつぶしを進めるもので、昔の BASIC っぽさを楽しめるように & 動作を確認しやすいようにした。 アルゴリズム的にはそんなに美しくはなっていないと思うが、動きとしては昔の BASIC 風になった感じはする。

Mozilla Firefox で試しながら書いていったのだが、なぜか Windows 版 Mozilla Firefox は putImageData が異様に遅いことが発覚してしまった。 HP の 3 万円ノート PC とは言え、同じ Mozilla Firefox なのに Raspberry Pi 4 の Ubuntu MATE の数倍、いや、そんなもんじゃないぐらい遅いってのは、いくらなんでも何か変な気がする。 500x500 を 1 ドットずつ埋めていったら Ubuntu MATE の Mozilla Firefox では普通に 1 秒以内に済んだのに、Windows 版の Mozilla Firefox ではいつまで経っても終わりそうにない感じだった。 同じ点を打つにしても fillRect のほうが速いらしいことがわかったのでそっちに変えた。

さてこれを 8086 アセンブリ言語で書いてみたい、というわけで、DOS プログラムで書いてみよう。 マウスはドライバーをあてにするならば int 33h を使うらしい。 DOSBox で試しているが、マウスポインターの位置と実際の座標がズレているなど、なんか挙動不審だなコイツ。 CGA 互換の画面モードは嫌いか? とりあえずマウスで線が引けるところまで作った。 線を引くルーチンは、ローカル変数を全部スタックに置いて全然レジスターを活用しないという、手書きアセンブリにあるまじき実装方法... いや、いいんだ。 塗りつぶしのほうをちゃんと書いてみたいだけなんだ。

2021/05/02 のコメントを読む・書く


03 (月)

%1 憲法記念日

いい天気。 のんびり。

きのうの F1 ポルトガル GP。 最初のほうでライコネンが追突リタイア、よそ見かなと思って今日コメントを見たらやはり、ステアリングでパラメーターをいじってモニターを見ていた時の判断ミスだったらしい。 何の言い訳もなく自分のミスだとシンプルなコメントはライコネンらしい。 また、チームメイトが無事に走り続けられてよかった、というのもライコネンらしいな。 この人は、マッサと組んでいたフェラーリ時代に、チャンピオンを獲った時の最終戦はマッサに援護してもらったところがあり、次の年はチャンピオンの権利がなくなった時点でマッサを援護していたのがあって、チームとしては非常にありがたいドライバーだろうなと。

んでまぁ、セーフティカーでちょっと明暗別れたドライバーもいたけど、結局ハミルトンは強い。 ロズベルグとやり合った時もそうだったけど、ギリギリのバトルができることを心の底から楽しんでいるように見えるし、それでいてタイヤをどう使うか、どう駆け引きするかを非常に落ち着いた視点からコントロールしているように見える。 セーフティカー開けで順位を落としても、あっという間に取り戻してしまう。 全盛期のミハエルシューマッハのように、すべてを支配下に置いているような感じに見える。 やっぱり、強いという言葉がぴったりだ。 ロズベルグに負けてからさらに強くなったと思う。 フェルスタッペンにもギリギリのバトルを仕掛けられる腕はあるが、まだ足りないところがあるのが見えてしまう。 せめて肝心のファステストラップ狙いの最終ラップはトラックリミット守ろうよ...

他には角田は今回は目立たなかった、というか、ガスリーもだいぶ苦労していて何かコースに合わなかったかな。 フェラーリもサインツが予選で速かったんだけど、決勝は苦労していたような。 ベッテルはトップ 10 スタートだったが最終的にストロールと同じ位置まで落ちた、とは言え最初の 2 戦に比べてすごく良くなってきたかと。 リカルドも下位スタートから追い上げ、タイヤをかなり持たせていて、今後が期待できそう。 アロンソも決勝はちょっとかっこいいところをみせてくれた。 いよいよ移籍組のパフォーマンスが上がってきたかな。 あっ、ペレスはまぁ最初順位を落として、最終的には無難な位置にはいたんだけど最後のファステストラップ狙いはちょっとタイミングが早かったかな。 まぁミディアムタイヤを限界まで引っ張っていたし、ソフトタイヤのおいしいタイミングを考えると難しいか。

%2 Paint in Assembly Language

例の塗りつぶしプログラムをアセンブリ言語で書いた: 20210503-paint.s. ビルドコマンド:

gcc -Wl,--oformat,binary,-Ttext,0x100 -nostdlib -nostdinc paint.s -o paint.com

だいぶ見直して単純化したが、動作速度は無視。 基本的には、範囲 (x1,y)-(x2,y) について、(x1,y) が壁でなければ、(x1,y) から左に壁を探索してから (x1,y) から右に壁を探索し、その間を塗りつぶす。 次に x1 を壁の右に進め、x2 を超えるまで繰り返す。 これで 1 行ぶんの塗りつぶし。 こうして塗りつぶしたところの、すぐ上とすぐ下の範囲を次の (x1,y)-(x2,y) にして繰り返す。 この時、すでに塗りつぶした範囲は避けるようにする。 開始時は開始点 (x,y) を (x1,y) と (x2,y) に当てはめてスタートする。 まぁこれだけなんだけど、すでに塗りつぶした範囲を避ける方法にこないだから悩んでいたわけだ。

JavaScript で書いたものは C でいうところの linked list みたいなものを使った。 アセンブリ言語でそれを書くには malloc/free がないとつらいものがある。 そこで配列みたいな形にした。

これをスタックに積むことでリストに追加相当の処理にした。 長さを先に積んで、後で可変長の範囲を配列として積む。 可変長なので混ざると面倒くさいから、上を先に見てぶつかる範囲を全部見つけて、次に下を見て... とやっている。

んで、取り出す時は塗りつぶした範囲を見てまず上の行、次に下の行と行くわけだが、その時に、このリストに入れておいた配列と、他にリストに残っている塗りつぶし範囲を見直して塗りつぶし済みを避ける。 JavaScript 版はリストに追加時と同じ探索処理をもう一度使って、新たな範囲を追加するという風にしたが、スタックに積んじゃったから追加は難しいので、毎回リストをたどる。 んで避けるところ、JavaScript 版はそれ用のピクセル読み取りメソッドを実装したが、今回は実装方法を見直して、読み取り範囲を狭めることにした。

最初は (x1,y) から左に向かってチェックなので、もっとも進むと左端 x=0 だが、この x を決める。 ぶつかる範囲があったら、その右側に x をずらしていく。 結果 x1 を超えたらそもそも左に向かってのチェックは不要ということ。 超えなければその x に到達するまで左に向かう。 右に向かうのはその反対、右端をぶつかる範囲の左側にずらしていく。

それで x2 まで残りがある時の続きの処理だが、面倒くさくなって超手抜き実装をしてしまった。 左に向かう処理の左端を、x=0 でなく塗りつぶした右側の壁の右に変えて、左に向かってチェックをやり直す。 向かうったって左には一歩も進めないんだが、その点がぶつかっているかどうかを見なければならないので、そのまま流用した。 欠点は、そこがぶつかっていなかった時は、実際に点を読み取って壁かどうかをチェックしなければならないが、壁だったらまた同じ処理のやり直しになるところだ。 本当は、ぶつからない範囲がどこまであるか、を見つけて、そこまでは一気に探索を進めるのが理想だ。

あと、リストからの削除は、あろうことかメモリーコピーにしてある。 スタック内でメモリーコピーを行い、スタックポインターを巻き戻す。 めちゃくちゃ安直なアイディアで実行時間は大きくなるに違いないが、これで malloc/free も余計な管理情報もすべて不要になりメモリー使用量は抑えられる。

今回スタック上のローカル変数を多用しているが、よりによってプリプロセッサすら使わずに書いてしまったのでめっちゃ読みにくいwww さすがに -2(%bp) みたいなのが名前で参照できないのは厳しいw 拡張子を大文字 .S にしておけば C のプリプロセッサが使えるんだよな。 それぐらいは使って書いたほうが良かった...

あと GNU as で 8086 向けのコードを書く場合、以下の 2 行で始めるといいようだ:

	.code16
	.arch	i8086

.arch は条件ジャンプの距離が遠くなる場合の対処にきいてきて、書いておかないと 0f で始まる near 条件ジャンプが使われる。

%3 BASIC

さてここで例の BASIC 実装を眺めてみる:

GW-BASIC/ADVGRP.ASM at edf82c2ebf6bfe099c2054e0ae125c3efe5769c4 - microsoft/GW-BASIC - GitHub

ウーン、わからん! わからんがおおざっぱに左にスキャンと右にスキャンがありそうだし、キュー (待ち行列、FIFO) の実装もあるようだ。 なんか LAHF と SAHF が無駄に並んでいるところがあったり、無駄にレジスターに即値やメモリーの値を入れてからレジスター同士の演算をしているところがあったり、16bit を little endian のままわざわざ 8bit ずつ読み書きしているところがあったりして、なんでこんな無駄なことしているんだろうと思ったが、[A] とか [B] とかコメントに書いてあるのを見ると、これってもしかして 8080 向けコードを変換したもの がベースか!? 当時もこんな無駄なコードを使っていたんだなw 遅くても動けば OK っていうのは意外とよくあるんだよね。

INS86 っていうのも謎なんだが、それも何か変換絡みなのかなぁ。

キューの初期化で 1000 バイト空いていたらスタート、空いていなかったらガベージコレクションをして 12 バイト切っていたら out of memory っていうのがあって、何かもういろいろと時代を感じる。 もちろんキューに入れる時にも out of memory に飛ぶパターンはある。 本当に塗りつぶしって処理は複雑なんだ。 キューはひとつで 6 バイト、エントリーに何を入れているのかはよくわからん... なんかでも、あれだな、今見ている位置を保存する領域は別にあって、それはインデックスだけキューにぶっ込んでいるっぽいな?

サブルーチンの入出力の仕様がコメントにないのが読みづらいところだ。 どのレジスターが何だ、どのメモリーが何だ、って情報があればだいぶ追いやすいのだが。 "ALREADY-PAINTED FLAG" が "MACHINE DEPENDENT GRAPHICS ROUTINES" から返されるのは気になるところ。 見た感じは SCAN が同時に描画もしているのかなぁ。 でも機種依存ルーチンでどうやって判断しているんだ? さっぱりわからん。

2021/05/03 のコメントを読む・書く


04 (火)

%1 みどりの日

Green Day. いい天気。 昼寝しまくった。

『るろうに剣心』のアニメ版、また続きが配信されている。 30 話まで見た。 第二十八幕でエンディングテーマが T.M.Revolution になる。 T.M.Revolution はアルバム新品で買ったけど、アニメのテーマ曲を歌っていたのは知らなかったんだよな。 っていうかアルバム買ったのはアニメの 3 年ぐらい後か。

%2 BASIC

GW-BASIC のコードを眺めていたら読み方がわかってきた。 INS86 は機械語直接指定で、なんと 8 進数だ。 10 進数に D とついているケースがある。 INS86 は 8 進数固定のようだが、それ以外で 8 進数に O をつけて書かれているところもあり、見た目で数字と読み間違えるので混乱する。 DB でバイト単位のデータを書くのは普通だが、なぜか数字に OFFSET がついている場合があって理由はよくわからない。 あと、数字に LOW とついているのがちょくちょく見られるが、これは 8080 由来の何かだろうか。 たぶん下位バイトを意味するんだろうと思う。

で、PAINT の実装の入口に CALL SCAN1 とあるのが、塗りつぶし処理関連のスキャンかと思っていたけど、よくよく読んでみたらこれはパラメーターの読み取りだ。 PAINT の座標の次の次の引数はオプショナルだが、それを読み取るのにまず , を読み取って、その次の引数を読み取る、みたいなコードが入っていて、やっぱり インタープリターだなぁ って感じがする。 GW-BASIC や昔の IBM BASIC は SAVE の時のデフォルトはバイナリフォーマットになっているんだけど、その中身を覗いても、( ), がそのまま入っている。 キーワードは先に解釈されてバイナリで保持されているが、こうして一部の文字はそのままになっていて実行時解釈なのである。 実行時にキーワード解釈するよりは若干速くなったんだろうな。 もっと古いであろう MSX BASIC は、スペースを全部抜いても実行できるので、保存形式は知らないんだけどたぶんテキスト形式のままで扱っていたんだろうと思う。 GW-BASIC もキーワードを書き間違えればそのままテキストで保存される。

そういえば PAINT の色の指定にはパターンも指定できるんだった。 GW-BASIC のソースコードを見てもそれをどう処理しているのか全然わからない。 いや、わからないっていうか、これ実装が入ってなくないか? LINE のほうの実装を見ても、スタイル引数がないぞ?

さて塗りつぶし処理なんだけど、塗りつぶし済みの判定をどうしているのかの謎が解けた。 gwbasic.exe でわかりやすい例を作った:

塗りつぶし挙動観察

ようするに横方向にボーダー探索した時にすべてが塗りつぶしの色になっていたら塗りつぶし済み判定のようだ。 スタートラインについてはその判定がされておらず、何もなかったかのように塗りつぶしが行われている。 左上と右上で挙動が違うのはおもしろいところで、最初に右端を見つけてスタートしているのか? いやー、GW-BASIC のコードを見てもそんな風には見えないんだけどなぁ。

GW-BASIC 的にはたぶん SCANR1 で右塗りつぶし、現在位置は変わらず。 SCANL1 が左塗りつぶしで、たぶん現在位置のひとつ左からスタートかな。 こっちは現在位置も移動するんだと思う。 んでこいつらは DX に見るべき範囲の長さを指定できるのかな、たぶん。 だから、キューから取り出したところの上下に対して SCANR1 がひとつも塗れなかったらそのエントリーは終わりにしている。 その後 SCANL1 をやって、塗りつぶしをしたらそれは OVERHANG ってコメントにある。 自分で実装をしてみたおかげでそのへんまでは何となく理解できる。

が、とにかく、マシン依存ルーチンの入出力を推測するしかないのが厳しい。 レジスターの内容すらわからないのに、そこに グローバル変数 も現れるからつらさ倍増だ。 グローバル変数が多いのは、 20 世紀のコード って感じがするよね。

ああ、そうか、キューから取り出しての SCANR1 が、塗りつぶし済みかどうかをチェックはしていないのか? SCANL1 はチェックがある。 だから左上から下に進んでいくと右側 overhang を上に向かって見てしまうのか? だけどじゃあ下にいかないのはなんでだ。 そのへんガッツリ理解するのはなかなか大変そうだ。

2021/05/04 のコメントを読む・書く


05 (水)

%1 こどもの日

Children's Day. 昼頃から雨が降ったりやんだり? あと時折風が強かった。

%2 BASIC の PAINT を理解した! (キリッ

まず、なんだ、えっと、キューに入れる 6 バイトなんだけど。 1 バイトは上下の方向。 最上位ビットがセットで上、セットされていなければ下だが、1 ビット左シフト (ADD) 後 0 になると終了を意味するので、出だしは 64 と 192 という値を使っている。 左シフト (ADD) でフラグレジスター経由で値を取り出し完了を含め一発把握が目的のよう。 キューが空になった時に 0 を返す。 もう 1 バイトはたぶん、VRAM の 1 バイト内の位置 (CMASK とあるからビットマスクか?) だと思う。 んで 2 バイトが VRAM のアドレス、残り 2 バイトが見るべき幅だ。 なお機種依存コードは別にあるので、たぶん必ずしも VRAM アドレスである必要はない。 ADDRESS と書いてあるからアドレスのつもりなんだろうけど、実質は位置を表すのに 24 ビットをまるまる使っても動くんじゃないかと思う。 その 24 ビットの現在の位置ってのは具体的には機種依存コードで扱っていて、FETCHC で位置読み取り、STOREC で位置変更のよう。

 #####
 #111#
#2222#
 #333#
 #####

こんな感じで 1 のどこかから塗りつぶしを開始した時、最初は SCANRSCANL を使って左右を端まで埋める。 そして現在位置は左端の 1 に。 次に下に行くようのエントリーを、1 の範囲と下方向という情報でキューに入れ、上に行くのはキューには入れずにいきなり上方向をキューから取り出した時と同じ状態にして開始。 それで現在位置を 1 の上にして SCANR をする。

このとき DX には調べる幅が入っている。 SCANR は現在位置がボーダーでもこの数をデクリメントして 0 にならなければ右に進めて繰り返す、んだと思う。 まぁ全部ボーダーだから終わり、ひとつも塗れなかったらゼロフラグがセットで、キューの取り出しへ。

キューを取り出しまた左上の 1 の位置に戻り、今度は下をチェックする。 SCANR が今度は最初からボーダーなしで 3 つ分を見つけ 2 のところを 3 つ分塗りつぶす。 SKPCNT はおそらく 3 のまま、MOVCNT は 3 になると思う。 そしたら左上の 1 の下に戻り、今度は SCANL で左側の 2 も塗る。 塗ったのが 1 つだけなので 2 を引けば -1 で OVERHANG にはならない。 その 1 と MOVCNT の 3 を足し、左端の 2 から 4 つの幅で、下方向のエントリーをキューに追加。 ちょうど SKPCNT=MOVCNT で終わっているのでこのエントリーは終わり。

そして最後は左端の 2 の下から 4 つ分でスタート、SCANR は最初のボーダーをスキップして SKPCNT を 3 に減らし MOVCNT は 3 か。 その下は最初の 1 の上と同じでひとつも塗れないから終了。

方向について出だしは 64 と 192 だが、その後はビット反転をしている。 つまり... 0x40 の反転で 0xbf, 0xc0 の反転で 0x3f があり得る。

きのうの話で左から右に行ってしまうのは SCANR1 で塗りつぶし済みチェックをせずに RIGHT OVERHANG を見に行ってしまうという理解で正しいと思う。 それで下に行かないのは ENTSLR が塗りつぶし済みフラグを見ているからだ。 左右どちらとも塗りつぶし済みの場合にはエントリーを登録しない作りになっている。 順番としてはその下に行かない判定の後、SCANR の終わり位置に戻り、RIGHT OVERHANG 判定になる。 そしてなんと、左に 1 ドットずつ LEFTC でずらしていって、キューに入れたい左端の位置を出している。 NEGHL はマクロで neg %bx である。 きのうの絵の左上で行くと、真ん中の塗りつぶし済みラインまで降りてきた時、SKPCNT には 7, それは減らされずに、MOVCNT には 15 が入るかな? 7-15=-8 が負なので OVERHANG 判定、neg して 2 引いて 6, それに 1 を足した 7 回左移動。 15 ドット塗った右端の次の位置から左に 7 回、16-7=9 で、ちょうど (200+16*J+9,Y+8) の位置に来て、そこから上向きのエントリーを追加することになる。 解決!

ってまぁつべこべ書いても何か間違っているかも知れないので、GW-BASIC の PAINT ルーチンだけ JavaScript に移植した。 キューの処理はさすがに面倒くさいから独自で書いたが、他はほぼほぼそっくりそのまま。 位置は X と Y を 12 ビットずつにわけて 24 ビットにして入れてある。 (おかげでデバッグが面倒だった。)

20210505-canvas2.html

書いてみてわかったのは SCANR の中でボーダースキップ後に CSAVEACSAVEM を更新しないとつじつまが合わないこと。 後は上に書いた話でだいたい合っていたと思う。

理解できたところで、必要そうなところをひたすら探索していく感じで結構泥臭い実装というか、性能重視でもないし、案外メモリー使用量を抑えている感じでもないような。 特に 8080 由来の無駄コードはひどくて、こんなのが 1980 年代ののろまなパソコンで使われていたとはなぁ... まぁ PAINT って本当に面倒くさいので書き直す気もしなかったのか、いや、パターン塗りつぶし対応が後で入ったわけだから、誰かは書き直したのか。 いや待って、パターン塗りつぶしの時は塗りつぶし済み判定できなくない? あれ?

2021/05/05 のコメントを読む・書く


06 (木)

%1 休暇

朝は曇り、その後は晴れて暑くなった。 のんびり。

曇っていた間にポケモン GO ウォーキングをした。 1 時間以上歩いたが途中止まっていた時間もあり、6200 歩。 昼に弁当買いに行った時にも少しポケモン GO 寄り道をしたがそれでも 3000 歩程度で、1 万歩には到達しなかったようだ。

テレビアニメ『スーパーカブ』4 話。 夏休みまでカッパ持っていなかったのか? エンジンオイル交換を店の人に 100km, 500km そして 1000km サイクルと教えられているシーンがあったが、スーパーカブなら指定は 3000km だろ? 半分にしても 1500km だよ。 だいたい 1000km も乗ったならドライブチェーンの注油もしろよ... チェーンカバーがついているから普通のバイクよりは汚れにくいだろうけれども。 あと、あんな長さのめがねレンチでドレンボルトがゆるまないって、それ締めすぎじゃないのw 1000km の件といいいい加減なバイク屋だなw

んでついでで鬼滅の刃が 14 話まであったのを途中から見てしまった。 正月に全部見たのにな。 まぁテンポがいい作品で、やっぱり善逸が技を繰り出すシーンは好きだなぁw 敵が一番面食らうタイプだと思うw

%2 GW-BASIC

例のソースコード。 DB OFFSET MINUTK というのがあって、MINUTK って何だろうと調べてびっくり。 キーワードとしては IBMRES.ASM の中にある。 だが QQ とか T とか、なんだそりゃ? って感じのコードになっている。

んで IBMRES.H というのを見ると、マクロで T の定義がある。 QQ をインクリメントして、指定のキーワードを export するっていうんだな。 でもキーワードが全部 DUMMY だからあんまり意味はないな。 とにかく何か数字を割り当てて export されている。 これたぶん、GNU as で言うところの foo=100;.global foo と同じで、そのシンボル名でアドレスとして定数を共有しているんだろう。 GNU as でこれを $foo として他ファイルから取り出したら 8 ビットでは取り出せない (と思う) んだが、MASM ではどうも LOW OFFSET を付ければ取り出せていたようだ。

まぁ問題は QQ の出だしはだいぶ上の 128 で始まり、そこには R2R がうじゃうじゃ並んでいる。 先頭は R2 END,ENDST とある。 なんだこりゃー、って思ったらまたさっきの IBMRES.H である。 R2 もまたマクロであり、ENDST を外部参照で、DW でおそらくそのアドレスを書いて、QQ をインクリメントし、...ここの & は連結か? $END という名前にインクリメントした QQ を入れて export するっていうのかな。

とにかく MASM のマクロを結構活用しているんだなと。 それでこれは、各キーワードに対する内部用コードの割り当てと呼び出し用のアドレステーブルを構築しているんだな。 ENDENDST というルーチンが呼び出し先で、コードは 129 ってことではないか。 たぶん、バイナリ保存したプログラムにはこのコードが使われていたのではないか。 冒頭の MINUTK はたぶん 1 文字の演算子に対するもので、ステートメントや関数じゃないので呼び出しアドレスは不要で、単にコードの割り当てだけってことかな。

じゃあその END の文字列定義はというと同じファイルで下のほうに Q ってのがある。 頭文字で振り分けるぐらいのことはしていたんだな。 Q のマクロ定義を見るとごちゃごちゃと... なんだこれ... MASM のドキュメントは一応 Microsoft のサイトで今も見られるようで、それを参考に何となく読めそう。 頭文字を消した上で DB に 1 文字ずつ与えているのか。 なんか、すごいな。

コードセグメントとデータセグメントは別のようで、コードセグメントへの書き込みはおそらくしていなさそう。 INS86 で 56 というのがついているのがコードセグメントのオーバーライドで、どれも読み取りに見える。 これはおそらくもともと ROM に積む用途があったコードがベースだからだと思う。 そういう意味で行儀が悪いコードではないんだが、CALL した先で POP で戻り番地を取り出して、CALL 命令の次に書かれている引数を読み取ったり、RET するかしないかの条件ジャンプで $+3 を使ったり (条件ジャンプ 2 バイトと RET 1 バイトを飛ばす)、次の 2 バイト命令をスキップさせるためにジャンプ命令では 2 バイト必要なので、2 バイト即値オペランドの命令を入れたりと、そういった昔のプログラムあるあるな小技は多用されている印象。 特に最後のはコメントを見ると別の命令が書いてあるから、8080 時代からあったんだろう。

CALL 先で POP してってのは自分も書いたことはあって、あれは何を参考にしたんだったか... 書きやすいのは書きやすいんだけど、デバッグする時大変なんだよなこれ。 コードとデータが混ざるから、逆アセンブルがぐちゃぐちゃになる。 2 バイト即値オペランドの opcode を入れて命令を飛ばしちゃうのは、日高徹「PC-9801 シリーズ マシン語ゲームグラフィックス」で見たような気がする。 よくそんなこと思いつくなー、なんて当時 (1996 年頃?) は思った気がするけど、どうも常套手段だったんだな。

2021/05/06 のコメントを読む・書く


07 (金)

%1 休暇

昼過ぎから雨が降ったりやんだり。 のんびり。

テレビドラマ『ゆるキャン△ 2』。 6 話。 野外活動サークルの 2 人とお友達が極寒の山中湖でやばい目に遭いそうな話。 次回が解決編か? 今回は珍しく飯テロな場面がなかったな。 美味そうな想像から材料買っただけだったw

テレビでやってた映画『タイタニック』(原題: Titanic)。 1997 年のアメリカ映画。 この映画はレンタル DVD で 20 年前に見たんだったな。 195 分もあったとは。 そりゃ 2 回に分けてになるわけだな。 101 歳の役、86〜87 歳とはいえ顔のメイクでシミやら何やらうまいこと表現してあるなぁ。 船のほうはミニチュア撮影だからかやや重みがない動きに感じられる。 機関室を通り抜けるシーンは何となく記憶にあったけど、車に入り込むシーンは完全に記憶から消えていた。

%2 空豆

この前、空豆を買ったので、ここ数日で食べた。 さやを開くとふかふかの布団のような (?) ところに豆が何粒か寝て (?) おり、それを取り出して鍋に突っ込む。 中の皮も剥くって話も聞いたんだけど、そのまま圧力鍋に入れて米とともに炊いたらまぁ味のほうは普通においしかった。 中のは薄皮って言うんだな。 硬いって聞いたけど別に硬くなかったのは、あれか、圧力鍋調理だからか? あるいは 5 分加圧して 10 分放置が長いからか。

2021/05/07 のコメントを読む・書く


08 (土)

%1 どようび

いい天気。 のんびり。

GW-BASIC のソースコード、この前は一部のルーチンを取り出して手作業で JavaScript に書き写したが、何かうまいこと自動化できないかな。 と思って考えていたが、MASM も古いのに意外といろいろ凝ったことをしているような気もする。 ASSUME を書いておくとどのセグメントを使うのかアセンブラーが判断してくれる、というのと、NEAR, WORD といった型が存在するところ。 小学生の頃は MASM を結構使っていたけど、その後 LSI C-86 試食版を使うようになってからは付属の R86 アセンブラーのほうをよく使っていたので、MASM にあんまりいい思い出はないw

まぁでも MASM が作られた時代と違って、今時は豊富なリソースをふんだんに使うお気軽プログラミングが可能である。 JavaScript で GW-BASIC のソースコード全体を変数に入れ、解釈してアセンブルとリンクを行うようなことも全然問題なく実現可能なはず。 なおそれをする場合 JavaScript には template literal という文法が存在しており、複数行の文字列を簡単に表現できる。 ソースコードでは \\ が出てくるところだけエスケープが必要。 他に ${...} もエスケープが必要だがそんなパターンは出てこない。 $ だけ、あるいは $ の後ろに別の文字が来るならエスケープしなくて良いらしい。

%2 新型ウイルス

高齢者向けワクチン接種がちょっとずつ始まっているようで、やはり都市部のほうがやや予約が難しい状況がありそうではあるものの、これからどんどん入荷されてくるからね、ペースを上げて接種を進めていくステージに入り始めている。 うれしいな。 人類はすごいな。 いやほんとに。

オリンピックがどうなるのやらという話もあるけど、オリンピックに向けて準備を進めてきた選手や関係者のことを考えると、せっかくすばらしいワクチンもできていることだし、まだ 2 か月あるんだから、ぜひワクチン接種を進めて、開催してほしいな。 自転車競技等、公道を使う競技は観客の制限が難しいところがあるだろうから、そこは中止にするか何か、あるかも知れないけど、競技場を使う競技は、無観客でやればいいと思うんだけどなー。

緊急事態宣言は、相変わらず終わりの判断条件の定義がされないもんだから、いろんなところで影響が出ているようだが... とにかくやっかいなのは変異ウイルス、 今まで大丈夫だった は通用しないのだ。 エビデンスエビデンスと叫ぶ人達が見受けられるが、去年だって、3 つの密を避けようという提案も、マスクを付けようというのも、エビデンスはない段階で言われていたわけで。 ヤバそうな条件が見つかったら、エビデンスがなくとも、なるべく早く共有し、皆で避けてみよう、というのが去年うまくいったやり方なんだと思う。 それから何か月もかけて条件が見直されて、このぐらいなら何とかなりそうという何となくの目安ができてしまったから、未だにその条件を元に話をする人がいるんだ。 今年の冬頃までは正しかったが、残念ながら今の変異ウイルスにそれでは対抗できないんだ。

Twitter で見ていると、大阪の危機に至る過程なんか、50 代以下での重症度合いの多さや肺炎の進行の速さなど、お医者さん達が危機感を伝える tweet から、1 週間ぐらい以上遅れて、知事の発言やら報道やらに現れるみたいなところがあり、その時間差だけでももったいないのに、そこからさらに数日あいて制限をかけても、肝心の住民に危機感が伝わらず、みたいなところがあったように思える。 お医者さん達の tweets は興味深いものが多く、特に去年なら会食やら居酒屋やらきっかけになりそうなところを見つけ出せたけど、最近はそういうのがないのにというケースが増えているという tweet があり、やはり対策レベルを上げる必要があるなと感じたものだが、ゴールデンウィークに実際に見た光景は、閉鎖されている都立公園駐車場の、隣の小さな飛行場の駐車場に車がたくさんとまっていて、公園がにぎやかってやつであり、こいつら 1 か月前のニュースしか知らないのかなみたいな気分にさせられたわけである。

ま、他人のことをあーだこーだ言ってもしょうがないんで、自分がやることをやるだけだが、このまま減らなければ外食禁止もあり得るんじゃないかな。 歩きたばこやたばこのポイ捨てが多くて路上喫煙禁止条例ができたのを思い出す。 知ろうとしない人達にはわかりようがないだろうが、知っている人から見れば自業自得となる。

2021/05/08 のコメントを読む・書く


09 (日)

%1 にちようび

連休最終日。 いい天気。 暑い日。

またテレビアニメの『鬼滅の刃』を 26 話まで見てしまったw アメリカ合衆国でも劇場版も公開されて非常にうまくいっているようで、本当にすごい。

MASM の古いバージョンのバイナリが、Microsoft が公開している MS-DOS のソースコードに含まれているようだ。 懐かしいなと思ってちょっと触ってみたんだが、使い方を覚えていないのが最高だ。 何しろ当時は /? が存在しない時代。 引数を全く付けないと完全にインタラクティブになっていて、インタラクティブに出てくる順番で引数を書くって仕様だったみたいだ。 昔どうやって使っていたかを探したら、; をつけるとそれ以降省略になるらしいことがわかった。

っていうか昔使っていたアセンブル用のコマンドを見たら、リンカーになぜか LSI Japan の LLD を使っていた! LLD は確か .COM ファイルを直接出力できたと思うんだけど、それは使わずに EXE2BIN を使っている風だった。 なんで LLD を使ったのかな、速いか何かだったかな、何にも覚えていない。 MASM の時は標準の LINK を使っていたと思っていたなぁ。

例の GW-BASIC のアセンブルができるかというと、INS86 が通らないし、行が長すぎるっぽいエラーなんかが出ていて、できそうに見えないw GW-BASIC のブートのところの処理を見ると、どうも DOS を前提とした実装が入っているみたいで、ROM で動かす用にはなっていないみたい。 さらには機種依存のコードは抜けているから、例えアセンブルができたところでリンクするにはいろいろ足りないものがあるけど。

F1 スペイン GP。 きのうの予選は何と言ってもハミルトンの 100 回目のポールポジション! 決勝は早々にセーフティカー、原因は角田、走行中にシステムがダウンして動けなくなってしまったようだ。 チームメイトのガスリーは、スタート時の停止位置を少し通り過ぎてしまったためペナルティを受けてしまい、チームとしてはさんざんな週末か。 それでも下位チーム同士の接近戦を制し 1 ポイントを獲得したのは見事。 トップ争いは、スタートでフェルスタッペンがトップに立ったものの、ペレスが上に上がってこれなかったので、防戦一方のフェルスタッペンを、メルセデスが強力な 2 回ピットストップ戦略でぶち抜いて行った。 ハミルトンの、スタートでは順位を落としてでも接触は避け、その後は離されないように速いペースを維持してプレッシャーをかけ続け、そのまま走り続けてもオーバーテイク成功しそうなところを、もう一度タイヤ交換してそこからハイペースで走り続けて、相手のタイヤが抵抗できない状態のところで難なくオーバーテイクっていう、やっぱり全盛期のミハエルシューマッハみたいな強さだよ。

2021/05/09 のコメントを読む・書く


prev, this, next

/var/log/hdk.log コメント一覧

トップ / 日記索引 / 日記 (2021 年 5 月上旬)

Hideki EIRAKU