/var/log/hdk.log

2022 年 8 月下旬

prev, this, next


20 (土)

%1 どようび

晴れていたと思ったが夜は雨が降ったっぽいな?

"背筋が GUUUN 美姿勢座椅子プレミアム" っていううさんくさい座椅子が届いたので、入れ替えてみた。 背もたれを抱きかかえるようにしても使えるという売りだが、やってみるとそれはあんまり快適な感じはしない。 とりあえず普通に使うことにしよう。

スーパーフォーミュラ、もてぎ。 今日 1 戦、明日 1 戦の連戦になっている。 YouTube の配信で見た。 山本が見事なポールトゥウィンだったが、去年チーム移籍してから表彰台すらなかったらしく、久しぶりの勝利に中嶋悟監督もうれしそうだった。 予選 Q1 はギリギリだったのが Q2 で見事ポールポジション、決勝は雨になったが、さすが 3 度のチャンピオン、完璧な走りだった。 終盤にセーフティカーが入って、どうなるかと思ったが、まったく危ないところがなくて、10 年前のライコネンの I know what to do を思い出したよw まぁ後のコメントを聞くと本人そこまで余裕はなかったみたいだが。

先月入れた emms が aac を再生してくれないことに気づいたので、(require 'emms-player-mplayer) の手前に以下を書き足した。

(require 'emms)
(setq emms-player-base-format-list (append '("aac") emms-player-base-format-list))

%2 DOS

たまに気になる MS-DOS のソースコード。 ここに含まれるバイナリ版 DEBUG.COM は P コマンドがないのだが、ソースコードをチラッと見たら ZTRACE という名称で実装は入っているみたいで、オプションをアセンブル時に有効にしておかないといけないのだろう。 気が向いたらビルドしてみようか。

で、中を見ていると KANJIIBMJAPVER なる定義名が出てくる。 どうやら KANJI というのは、MS_Kanji (Shift_JIS) 対応をしたものらしくて、2 バイト目に \ があるケースの対応などあるっぽい。 IBMVER だったかな、ってのもあってそれは IBMBIO.COM と IO.SYS の区別などあるみたいだから、これは IBM DOS かどうかだな。 日本では PC-98 版が有名だったので、IO.SYS も見慣れたものである。 じゃあ IBMJAPVER ってのは? デバッガーのコードを見ると、なんと NMI でパリティエラー判定みたいな実装があり、そこに IBMJAPVER があってポート A0H を読み取って何かやっている。 (どう見てもバグがあってちゃんと動かないけど。) これって IBM JX 用では!???

不思議なのは、確か IBM PCjr も NMI をキーボード用に使っているのは同じじゃなかったっけな。 DMA なんかも取っ払って CPU はミニマムモードで使うけちけち仕様だからな。 なので PCjr 版でも同じはずだが... んで実際の JX 用の DEBUG.COM のバイナリを見たら、パリティエラーのメッセージとそれを出力するっぽいコードはあったが、それを出力するフラグをセットする部分はなかった。 まぁ、そうだな。

あと、JX は発売が遅かったみたいだから、日本語 MS-DOS って PC-98 版が先に出たんじゃないかな。 それも同じ MS_Kanji 仕様なわけで、まず日本語対応をして、それから IBMJAPVER が入る流れだろうか? JX は漢字 ROM のアドレス配置が MS_Kanji だから文字コードができてからなのは間違いないわけだが...

2022/08/20 のコメントを読む・書く


21 (日)

%1 にちようび

涼しい日。

SUPER FORMULA もてぎ 2 連戦 2 戦目。 予選は山本はずいぶん下になっちゃったが、そのチームメイトの大湯がポールポジションを取った。 そうなるときのうに続いてポールトゥウィンが見られるか? と期待が高まってくるが、決勝は IMPUL の一台、関口が早めのピットインでアンダーカットに成功しピットイン組トップを走行。 しかしタイヤが持つか? と注目の中、関口のチームメイトである平川が反対の戦略、好ペースを維持したまま引っ張りに引っ張って、残り 10 周前後のところでピットイン! アウトラップは無理しなかったが、次の周にはタイヤが温まり、ポイントランキングトップの野尻をサクッとしとめて表彰台圏内、さらには次の牧野も攻略し、残り 2 周ほどで関口とのチームメイトバトル! 関口が何とかブロックに成功して勝ったが、どっちにしてもホンダ系コースでトヨタエンジンの IMPUL の 1-2 とはね。 とてもおもしろかった。 大湯は残念ながら最初のスティントのペースが良くなかったためだいぶ順位を落とした。 そのあたり、チーム力が足りないのか、ドライバー力が山本ほどないのか、わからないけど。

%2 DEBUG

MS-DOS のソースコードの DEBUG コマンドのビルドは、同梱されている MASM と LINK と EXE2BIN でいけるんだが、なぜか DEBCOM2.ASM だけ改行コードが LF になっていて、そのせいで MASM が失敗するので、事前に CRLF に変えておく必要がある。 それだけ。

で、やってみたらわかったんだけど、P コマンドは ZIBO の定義がどっちになっていてもエラーにはならない。 ZIBO は TRUE に設定されていて、普通にビルドしたらなじみのある P コマンドが使えるバージョンの DEBUG.COM になった。 FALSE にすると P コマンドはぱっと見は T コマンドと同じような挙動をしているように見えた。 (CALL の先に入っていった。) 同梱されている DEBUG.COM は P コマンドが Error になるが、そんなバージョンの DEBUG コマンドのソースコードはなさそうだ。

%3 カレンダーのプログラム

20220821-cal2.s

DOS 用の COM プログラムで小さい版を作ってみた。 MASM は面倒だったので gcc のアセンブラーで... かけ算・割り算命令も CALL や PUSH さえも一切使っていないので 8080/Z80 系への移植にも使えるかも知れない (?)。 この前のバージョンでやったような、26 をかけて 5 を足して 10 で割るなんていう演算は容量を食いすぎる。 月は 12 しかないんだ。 単にテーブル参照にしたほうが小さく済みそうだってことでそうしてみた。

今回の実装の謎仕様は、年を 400 で割った余りにするところまでは前のと同じだが、それを 20 で割った商と余りで、0 から 19 の整数値ふたつに分けるところ。 テーブルは 20 バイト長だが、ビットで分けて 3 種類のデータを入れてある。 20 で割った商のほうで 20 年単位の曜日の計算と 100 年単位の閏年除外判定をしている。 んで 20 で割った余りのほうは普通に足し算と閏年判定に使う。 で同じテーブルに月の曜日計算データも入れた。 前のと違って 1 月 2 月を前年 13 月 14 月の扱いにしていない代わりに、閏年の場合の 1 月 2 月は 20 バイトあるテーブルの余った部分に入れてある。 んでさらに翌月分までテーブルに入れても 20 バイトあるので足りる。 月の長さを曜日ベースで判定するのは前と同じ。 数字の出力はバッファー上で ASCII を直接インクリメントするスタイルにしてみた。

書いてみてわかったのは、前の仕様と違い動作確認が大変だ。 計算で行うのと違い、テーブルベースではテーブルの各要素が間違っていると変なことが起きてしまうから、テーブルの要素をすべて使うパターンを試さないといけない。 あと、どう見てもこのコードは数か月後に見たら自分でも理解できないと思うw

2022/08/21 のコメントを読む・書く


22 (月)

%1 げつようび

涼しい日。

座骨神経痛。 整形外科には 3 週間ぐらい行っていないな。 座骨神経痛のほうはちょくちょく出てはいるんだが、腰のあたりをもむといいような感じがする。 わからんけど。 背骨と脇腹の間らへんというか。 まだ試行錯誤中。

%2 CD

この前シングル CD の中古を何枚か買った。 一度ミニコンポで再生確認したが、実に面倒なので抽出してファイルで保存。

そんな感じでこの中ではどうやら売り上げ枚数的にはハッピーマンが一番レアキャラなようだ。 曲的にはめざましテレビにぴったりな明るい曲だけど。

シングルなんて基本買ってこなかったし、実家にあったのもあまりまじまじと見なかったので知らなかったけど、奥居 香と鈴木雅之のシングル CD には、ファンクラブの入会方法の案内が書いてあるようだ。 80 円切手 を同封して送れとか、80 円切手 を貼った返信用封筒を送れとか、それに送り先の 郵便番号が 3 桁 で、時代を感じすぎる... でも、わざわざシングルを買うのって結構ファンになってくれそうな人が多いのでは、という気もするので、狙いは正しかったのかも知れない。

まぁ、アルバムにも何かしらファンクラブへのアクセス方法の情報はついていたもんだけどね。 自分が最初に買ったルパン三世... じゃなくてその次に買ったのが T.M.Revolution だったが、CD EXTRA もあったし、インターネットの特設サイトもあった。 (Wikipedia によるとサイトは閉鎖されているらしい。)

2022/08/22 のコメントを読む・書く


23 (火)

%1 かようび

暑い日!

お昼を買いに行く時も、暑いので、スクーターを出して、弁当を注文してからできあがるまでの間に買い物を済ませた。 やっぱりお昼のドラッグストアは空いている感じだ。 お昼のスーパーマーケットはだいたいどこも混雑している気がするので、不思議な感じがする。 特に、弁当も少し取り扱いがあるこのドラッグストアが空いているとはね... まぁ弁当買いに来るなら隣にあるコンビニエンスストアのほうか、普通は。

そのドラッグストアは以前から SARS-CoV-2 のうさんくさい検査キット販売などに手を出しておりやる気満々なので、今は抗原検査やら PCR やらそれっぽいキーワードが印刷された紙が処方箋受付側の入口扉に貼られている。 正直誰が買うんだろう? と思っているが最近は事情が違うのかも知れない。

去年発熱して検査を受けた時は普通に発熱外来を受診して唾液 PCR 検査だった。 その時のクリニックが今も発熱外来を続けているかはわからないが、その時にはまだいつもの耳鼻咽喉科では検査をしていなかったのが、その後は新規でない人には検査をするようになったっぽい感じだったので、今度検査が必要になったらまた耳鼻咽喉科に連絡してみることになりそう。

まぁ、基礎疾患がある人や高齢者向けには専用の薬を出すこともあるけどそうでなければただの対症療法みたいなので、医療機関側としては自分で何とかしてくれってところもあるだろうな。 ただの診断書のためだけに検査受けに来ないでほしいってのはあるみたい。 自分なんかは診断書をもらっても特に役に立つ用途もないわけで、もし何か症状が出てもそのまま様子見パターンかもという気もする。 医師によっては SARS-CoV-2 専用の薬の処方が難しいのは失敗だったねとする人もいるみたい。 高齢者の重症化を 8 割抑えられる薬だというから確かにそれをもっと使えていればと思うところがあるんだろう。 しかし素人考えでは、発熱外来に待ち行列ができる状況においてはそもそも、たどり着いた時には手遅れ、って高齢者も結構多いんじゃないのって気もする。 Fork 爆弾で増えたプロセスひとつひとつにちまちまとデバッガーをアタッチして対処してもね。

2022/08/23 のコメントを読む・書く


24 (水)

%1 すいようび

昼間は晴れていた。 夕方頃から時々雨が降っていた。

つばを飲み込むときに微妙にのどに違和感がある。 例のアレでなければいいが。 単に仕事で英語の文章を読むのについつい音読しているせいなら別に...

%2 蟹味噌

PC-98 のフリーソフトのゲームで蟹味噌というのがあって、DOSBox-X みたいな PC-98 エミュレーターで遊べるんだけど、スコアファイルが壊れてしまうという残念な 2000 年問題がある。 年が 2 桁で入るべきところに 3 桁入ってズレてしまう上に、終端文字も壊してしまうため時刻が 2 回繰り返しでスコアファイルに記録されてしまい、読み込みの際には壊れているとしてそれ以下のスコアが消えてしまう。 これを何とか対策できないかと思って、前に見た時にはどうもバイナリが圧縮されていて面倒だなってなったんだけど、蟹味噌の配布物 (定番フリーソフトとして本で販売されていたもののコピー) が出てきて、それを見たら圧縮されていなかったので、もしかしたら DIET か何かを使って後から圧縮していたのかな、ディスクの空き容量不足で。

ってなわけで圧縮されていないのが出てきたならさっそく調べるしかない。 ドキュメントにある通り C で書かれていて、崩れ方から sprintf%02d/%02d/%02d みたいなことをしているのは C のプログラミング経験があれば容易に想像できる。 最初、年を 1900 引いているのかな、と思って immediate operand の 1900 を探したら何かが見つかったが、これは直接関係のない標準 C ライブラリの一部な気がしてきた。 %02d/%02d/%02d のほうのオフセットアドレスを特定し、そのアドレスを探したらいかにも sprintf っぽい push と call の流れだ。 その前にも call がふたつぐらいあり、おそらく time(NULL)localtime か何かの関数呼び出しだろう。 1970 年からの秒数にした上で日付に変換だから、やはり 1900 は関係ないわけだ。 localtime の仕様で月は 0 から 11 になっていて、実際 1 を加えているコードがある。 年は 1900 を引いた値というのが返されるのを、そのまま使っているっぽい。 となればこれを 100 で割った余りにすればいいんだ。 (別に 2000 年より前の日付で動かすことないから 100 を引いてもいいんだけどねw)

Win32 バイナリだと結構関数と関数の間に隙間があってこういう命令の追加に使えたもんだが、さすがに DOS のバイナリにそんな隙間はない。 じゃあ何ができるかというと、呼び出し規約の都合で関数の引数があるとどうしても push push call add がある。 80386 以降の 32 ビットモードはスタックポインターベースのアドレッシングが可能になったので、今時の C コンパイラーは全部 mov ですませていることが多いが、8086 の時はベースポインターを使うしかなかったのと、もしかしたら命令長の問題やスタック容量の問題もあったのかな、それで基本的には素直に push して call して add でスタックポインターを戻す、となる。 その add が 3 バイトあるし、別にすぐに戻さなくても問題はないので活用できる。

そんなわけで localtime か何かの call の後ろの add を取っ払って詰めて 3 バイトを手に入れ、さらにその近くの mov 2 バイトが xchg と置き換えても大丈夫だったのでもう 1 バイト手に入った。 後は年の push 命令 3 バイトを、mov aam cbtw push 命令の 7 バイトに置き換えて、100 で割った余りにする処理完成! スタックポインターが 2 ズレたままなので、sprintf の後の add に 2 足しておいた。 足さなくてもベースポインターから戻されるだろうから大丈夫な気もするけど、無関係なところを追うのは面倒なのでわかる範囲ですませる。

aam なので 8 ビット符号無し整数で 2155 年まで対応! いや、その前に DOS がたぶん 2079 年までな気がするし、そのさらに前に 2038 年問題がある。 あっ、そっか、もう 16 年もしたらこれもだめなんだな... Bio_100% 系は super.lib や MASTER.LIB の関係で C で書かれているゲームが多いから、2038 年でそのへん全滅しそうだな。 とりあえず localtime 等に入力する time_t を符号無しにすれば延命できる可能性はあるが、バイナリパッチですませるのは大変そうだ...

2022/08/24 のコメントを読む・書く


25 (木)

%1 もくようび

涼しい日。 エアコンを使わない在宅勤務。

きのうののどが変だったのはよくなっているし発熱もないのでまぁいいだろう。

『異世界おじさん』6 話。 まわりから見ると過酷な異世界思い出話。 現世は基本アパートの一室で話が進むのがおもしろい。 今回はラーメン屋がでてきたけど。

昼の弁当屋までの歩きに加え、夜ラーメン屋まで歩いて行ってきたら 1 万歩超えた。 例によって真っ暗な霊園を突っ切った。 霊園では滅多に人とすれ違わないのでマスクを外していても問題ない。

2022/08/25 のコメントを読む・書く


26 (金)

%1 きんようび

雨降ったのかな? 涼しいかと思いきやそこまで涼しくはなかったものの在宅勤務の間は扇風機のみで過ごせた。 が夜には室温 30 度になっていた。

テレビでやってた映画『耳をすませば』。 1995 年の邦画。

%2 ぽろりす

おとといの蟹味噌と同様、ぽろりす (Porolith) も 2000 年問題がある。 壊れ方はそっくり、壊れた後は自分で壊れていると言って起動しなくなる残念パターンだったはず。 中を見ると Microsoft の C ランタイムの文字列が含まれているようなので、そっくり同じパターンだろう、と思って例のフォーマット文字列のアドレスからコードを特定したはいいが、メモリーモデルが違った! データも関数もすべて far ポインターになっている。 ああー。

蟹味噌では add をつぶしたのと mov を xchg にかえて追加の 4 バイトを手に入れた。 今回も add をつぶして 3 バイトは簡単に手に入るが、localtime か何かが返すのも far ポインターであるためその後のコードが違い、面倒な感じになっている。 しかも、その C ライブラリの呼び出しも far call ということは、これセグメントは再配置対象だよな? となると call を移動するのはさらに困難を伴うだろう...

ウーン、と考えたあげく、%es と %ds を逆にして使うことにした。 その手前で movs のために %ds を待避して pop で戻している部分があり、そこから問題の箇所まで %ds を使っている気配がなかったので、それを勝手に %es に戻すようにして、後で %es を %ds に反映という形にした。 これはトリッキーで、呼び出した先のルーチンが %es を破壊していたらアウトだ。 まぁ、そこまでちゃんと調べずにやったので破壊されているかも知れないけど...w でもフォーマット文字列がちゃんと出ていたので結果的には大丈夫なんだろうな。

もしかしたら、あれだなぁ、time の返り値をローカル変数に入れてそのポインターを localtime か何かに渡すつくりだけど、それも far ポインターになって長くなっているから、これを mov でやらずに、わざと push push でやってしまうのが縮めるという意味では得策だったかな? いやでも、それをすると localtime の前に隙間ができるだけなので、ジャンプをして... あぁ、それでもいけるな、うん。

付属のドキュメントを読んでいると、GNU Indent でソースコードを整えた、みたいな話が書いてあってちょっと感動である。 30 年以上前のゲームだからね。 DJGPP やらの DOS エクステンダー系統も一応 1990 年だと登場し始めていた頃かも知れないが、まだ 32 ビット機が普及しているとは言い難い時期だもんな。 おそらくその頃は GNU indent みたいなユーティリティーは 16 ビット環境でコンパイルすることがまだ十分に想定されていたんだろうな。

2022/08/26 のコメントを読む・書く


27 (土)

%1 どようび

のんびり。

夕方ちょっとバイクに乗って、聖蹟桜ヶ丘のいろは坂を登ってロータリーをまわり、適当にぐねぐねと住宅地を通り抜けて帰った。 いろは坂 (多摩市)、耳をすませばのファンかなと思われるような歩行者がちらほら。

きのうのぽろりすのは time の返り値のところを push push に差し替える作戦でやってみるとセグメントレジスターを逆に使う必要がなくなり、ちょっと安心感が増した仕上がりとなった。 DOS 当時の C 呼び出し規約の細かいところなんて覚えていないんだけど、見た感じ %es は保存せずに書き換えているようだし、localtime か何かの引数も far ポインターで返されるのも far ポインターなので、%es が保持されると期待できるかは怪しい。

a2ps で作った PostScript を、画像にできないかと思っていろいろやったが、切り出すなら GIMP で開くのが手っ取り早いことがわかった。 ps2pdf で PDF に変換するとか、PostScript なり PDF なりを GhostScript に処理させるとか、いろいろあるんだけど、向きがおかしくなることがあるし、オプションもよくわからん。

binutils の objdump コマンドで逆アセンブルというのをよくやっているが、Win32 バイナリは普通に ELF 用でもいける感じなのに、残念ながら DOS バイナリは検出してくれない。 binutils のソースコードには msdos というキーワードがありそうなので、--target=msdos を指定して configure してみたらいけた。 make も一発、これで DOS バイナリを見るのが楽になるぞと思ったんだが、なんと .text セクションしか出てこないw 意味ねぇw さすがにちょっと適当過ぎやしないかw 一応、ヘッダーをスキップしたところから逆アセンブルしてくれるのと、アーキテクチャーがデフォルトで i8086 になるのは良いが、そうじゃないんだよー、セグメントや再配置情報を見たかったのにw

先月末に x0tigervncserver の HAVE_XDAMAGE を外す対策をしたつもりだったが、パッケージの一部だけを /usr/local/bin に置いたために結局 /usr/bin のバイナリが使われていてうまく動いていなかったことが発覚した。 Debian パッチなしで普通にビルドして /usr/local に入れたら、-localhost no--I-KNOW-THIS-IS-INSECURE もエラーになってしまい、こいつら Debian の拡張だったんか... っていう。

ニトリで携帯扇風機 HF3103 を買ってきた。 前に買ったうさんくさいのはファンが時々振動するしずっと放置していたら電池がなくなって動かなくなっていた。 いやまぁ、しばらく充電していたら突然ぴかっと光って復活したけど。 この HF3103 はモバイルバッテリー部と扇風機部が完全に分離するタイプだ。 どういうことかと言うと、手持ちの eneloop モバイルバッテリー KBC-L2A でも回せる。 消費電流的にはまずいかも知れないが、とりあえず回る。 なのでいざ使いたい時に電池が切れていても他が使えるというメリットがある。 それと... バッテリーでなくても、単なる USB 充電器につないでも回る。 いろんな用途に使えて便利かなと思った。

楽天トラベルのパック旅行 (飛行機 + 宿泊)、相変わらず時期を外せば安いみたい。 昨今の物価上昇はどこにいったのかというような値段だ。 ただ最近は空港の人混みがすごそうなので、狙うなら朝イチかなと。 朝イチは明らかに不人気なため、安いし、人も少ないし、空港駐車場も余裕とメリットがたくさん、だと思うが乗ってみないとわからないな。 欠点はレンタカーの営業時間の関係でレンタカーをセットで予約できないw

2022/08/27 のコメントを読む・書く


28 (日)

%1 にちようび

昼頃まで雨。 のんびり。

トイレにおいてある時計の電池が切れかけていたので交換しようとしたら液漏れしていた。 前回の交換が 2014 年だったようで、容量の少ない単四アルカリ乾電池を 8 年も使えばそりゃ液漏れもするか。 大学院修了時にもらった大学ロゴ入りの時計なので、その前は 2007 年だろう。 汚れた電池ボックスをペーパータオルで拭き取り、さらに歯ブラシで電極部分をゴシゴシこすって、それから未使用の電池 (期限切れだったけど) を入れたら、なんと電池を外す前の時刻から再開した。 電池残量警告マークも残っていて、数秒後に消えた。 10 分ぐらい電池を外していたはずだけど、よく残っていたな...

%2 デバイスドライバー

MS-DOS/DEVDRIV.DOC at 04a3d20ff411409ab98474892b2bb1713bde0f7f - microsoft/MS-DOS - GitHub

MS-DOS のソースコードの中に "MS-DOS 2.0 Device Drivers" というドキュメントを見つけた。 昔デバイスドライバーを書いてみたことはあるにはあるんだが、あの時は NEC 用 MS-DOS のマニュアルを参照していた気がする。 そのマニュアルがどんなだったか忘れたが、この英語のドキュメントは MSDOS 2.0 が出た当時の話ベースで書いてあっておもしろい。

RAMDISK.SYS というのが昔あったんだが、中を見るとやはりブロックデバイスとして実装されていて、指定容量の空っぽの FAT を構築するルーチンが中に入っているんだろうと思う。 あれ、そういえばデバイスドライバーの引数はどこに渡されるんだっけか?

デバイスドライバーがデバイスをドライブするものだという単純な事実を意識させられたのは大学生の頃だ。 オペレーティングシステムがデバイスへのアクセスを抽象化したインターフェイスを提供しており、アプリケーションは直接デバイスをドライブせず、オペレーティングシステムを介してデバイスドライバーがドライブする。 英語圏の人々にとってはごくごく自然なことだろうけど、自分らの感覚ではデバイスドライバーはデバイスドライバーという固有名詞のような存在であり、かつては CONFIG.SYS に設定を書いて組み込むものであった。 そこには日本語入力フロントエンドプロセッサとか、RAM ディスクとか、高速再起動プログラムとか、特にデバイスを必要としない (デバイスをドライブしていない) ものも多く存在していたけど、何も気にしていなかった。

DOS も一応そういうオペレーティングシステムとして作られたんだと思うけど、こうして公開されているソースコードを見ると中途半端でもある。 例えば FORMAT コマンドのソースコードには非公開の機種依存部分があり、そこは各メーカーが作る部分となっている。 ディスクのフォーマットが IOCTL あるいは何らかのインターフェイス経由にはなっていなかったんだよね。 まぁ Unix 由来と思われる ioctl も決して理想的なものではなくて、ある意味抽象化を諦めてしまったインターフェイスであり、後の Plan 9 ではそれを撤廃してデバイスドライバーもすべてをファイルベースで見せるようにしているし、その考え方の一部が Linux にも取り込まれて、sysfs 経由で機種依存でない形でデバイスの様々な追加情報にアクセスできるようになっている。

今振り返って DOS にほしかったデバイスドライバーは、キー入力と画面出力まわりだな。 あとタイマーか? キー入力はオペレーティングシステムの機能でもある程度はよかったが、カーソルキーのコードなどに機種依存部分があったし、押しっぱなしを検出したいゲーム用途的にはハードウェア直接制御が避けられなかった。 画面出力も ANSI エスケープシーケンスはかなり自由度を高めてくれはしたものの、遅かったのは否めないし、グラフィックスの描画については抽象化はほぼ何も無し。 IBM の BIOS でもドットが打てるのみ。 PC-98 に至っては BIOS は古くさい 8 色時代の機能しかなく、16 色については一応 PC-98 には GRAPH.SYS というのはあったが、これデバイスドライバーのていをしているものの、実態は専用の割り込みを使う代物だ。 特に DOS/V が出てきた時にそういう抽象化レイヤーができればよかったが、あれも IBM BIOS レベルでごちゃごちゃやっていたのが中心。 一太郎など市販の DOS アプリケーションは最後まで機種依存だった。 性能面を考えると描画のたびに IOCTL みたいなのを通すのは需要がなかったかなとは思うが、例えば far プロシージャーのアドレスをもらっていろいろやれるようにでもなっていたら、もう少し DOS 汎用プログラムが多かっただろうと思う。

2022/08/28 のコメントを読む・書く


29 (月)

%1 げつようび

涼しい日。

%2 IBM DOS

IBM DOS といっても MS-DOS の IBM 版なだけだが... きのう DEVDRIV.DOC を読んでいて気になったことがあった。 ブロックデバイスの MEDIA CHECK という呼び出しは、media が changed かどうか、あるいは不明かを返すものだという。 PC-98 ではフロッピーディスクの出し入れをハードウェア的に検知する機構があって、それに合わせて正確に値が返されていたものと思う。 しかし JX はそのようなハードウェアはなく、ディスケットを入れ忘れてアクセスした場合も、タイムアウトしてからエラーになっていた。 なので MEDIA CHECK の存在そのものは確か NEC のマニュアルで見て知っていたんだけど、DOS 2.x にはないものと思っていたような気がする。

で、そうするとその MEDIA CHECK はすべて不明と返していたのではないか? そのせいでやたら同じトラックを何度もアクセスしてディスケットがよく壊れていたのではないか? という疑問が浮かんできた。 DOS のデバイスドライバーはヘッダーの pointer をたどる一方向リスト形式になっているらしいので、RAM ディスクを組み込んで起動した上で、RAM ディスクのデバイスドライバーが読み込まれているアドレスを突き止め、そこからその一方向リストをたどって、ディスケットのブロックデバイスにたどり着けた。 そういうのはセグメント 200H にもろもろ読み込まれているらしい。 IBMBIO.COM の一部だな。

んでちょろっと見たところでは、単純に不明と返しているのではなく何か処理があるようで、もしかしたらハードドライブ絡みの処理なのかも知れないが理解できていない。 しかし改造はできる。 条件ジャンプを一か所無条件ジャンプに書き換えることで、 常に not been changed にしてしまおう。 ということで、改造版とそうでないのを、アクセス開始 LBA を表示するように改造した拙作エミュレーターで実行して比較! 案の定差が現れた。

ゲームを入れてあったディスケットで試したら差が少なかったが、CONFIG.SYS に BUFFERS=10 を書き加えたところ大きな差が出た。 それでも何度も FAT とルートディレクトリエントリを読み込んでいるんだけど、回数としては顕著に減る。 これだ... わざわざディスクキャッシュのプログラムなど実装して使っていたが (最初使っていたのは、手動でキャッシュクリアを指示する必要があったのとバグもあったために何度かディスケットを壊してしまい、次は自分で最低限の機能でランプが消えるまでキャッシュを保持するものを作って使っていた)、 本当に必要なもの はこれだったのかも知れない。 そのランプが消えるまでのアイディアを、DOS のブロックデバイスに適用すればよかったんだ。 まじめに作るならブロックデバイスのデバイスドライバーとして作成して、組み込み時にドライブ文字の範囲をシステムに組み込まれているディスケットのものと同一にしてフックする形になっていただろう。 同時に強引にキャラクターデバイスも追加して、一時的に長時間保持モードに設定できてもよかったかも知れない。 その場合はランプが消えるまでの時間を延長するか何かで見た目にもわかりやすいようにしておくと良かっただろう。

それ以外にも当時も実現できた可能性がある方法はあって、RAM ディスクの空き領域をディスクキャッシュとして使うという RAM ディスクデバイスドライバーも、作ることはできただろうなと。 RAM ディスクを自分で実装してみたいという気持ちがあの頃にあったなら、作れていたかも知れないけど、特になかったな。

ついでにおそろしいことを書くと、当時 BASIC で RAM に機械語を書き込んで実行するというテクニックは世界の常識だったわけだが、その時に何かのマニュアルか何かで見た DEF SEG=&H1A00 というのを何も考えずにいろんなところで使っていたのは、やっぱりよくなかったようだ。 普通に 64KiB の RAM ディスクを組み込んで立ち上げたらセグメントは 2435H あたりになっている。 つまり 1A00H は RAM ディスクの領域の一部とか、運が悪ければ DOS のバッファーとか、自作のディスクキャッシュの領域とかだった可能性もある。 素直に DEF SEG にして、VARPTR なんかを使うのが正解だったんだけど、全く知識が足りていなかったわけでね... オフセットアドレスがずれると面倒というのはあるが、後の機械語の知識があったらそんなのなんとでもなったよな。 16 バイト単位に合わせておけばセグメントで調整することもできたし。

2022/08/29 のコメントを読む・書く


30 (火)

%1 かようび

涼しい日。 在宅勤務。 今月 1 回しか出社してなくない??? ま、いいか。

Qrio Lock 時々アプリでアクセスして確認しているのだが、ピッと確認したら片側電池切れになっていた。 そういえば前に確認した時に残量低下の表示があったっけ... 忘れていた。 3V のリチウム電池 2 本だが、開放電圧を測ると 5.8V ぐらいはあった。 けっこうあるじゃんと思ったが、だめらしい。 予備に買ってあったのを開封して測ると 6.4V ぐらいあった。 なるほどね。

Qrio Lock の電池をかえなきゃなーと思いながら、ミーティング後にミニコンポの電源を入れようとリモコンを押しても電源が入らなかった。 最初はこのリモコンも電池切れかよと思っていたんだが、本体のボタンを押してもうんともすんとも言わない。 あれれ? こういう時は... IT 業界ではおなじみの、電源ケーブルを外して、しばらく待ってからつなぎ直す! という方法で復活した。 何だったんだ。

%2 F1

おとといの F1 ベルギー GP。 1 周目からルイスハミルトンがとても珍しいアクシデントを起こしてオイルをまき散らしてリタイヤしてしまい、その後ラティフィがとてもそれらしいスピンをやらかしてボッタスが被害に遭い、セーフティカー、それからフェルスタッペンがあまりにも無双するので若干見る気を無くしたw 2004 年のミハエルシューマッハかと思うほど、圧勝だ。 チームメイトも完全に置き去りにしていて、余分にピットインしても余裕で優勝だっただろうというほどペースに差があった。 フェラーリはルクレールは不運に遭い、サインツががんばっていた。 が本当に差がでかいんだよな。 ハミルトンのアクシデントがなかったとしても 1-2 に違いはなかっただろうと思えるほど。

ここに来てアルピーヌは確実に力をつけてきているし、ウィリアムズもアルボンは直線番長を最大限活かして入賞していた。 アルファタウリは今回ガスリーが入賞はしたんだけど、なんかマシン的にはいまいちな感じがする。 直線番長のアルボンが後ろにいたから何とかなっただけで、ストロールやらノリスやらには前に行かれていても不思議はない感じ。 まぁでもハースが今回悪かったのや、メルセデスも予選いまいちだったのを見ても、コース特性もあるんだろうな。

2022/08/30 のコメントを読む・書く


31 (水)

%1 休暇

耳鼻科。 いつもの。

耳鼻科に行くってことは職場の近くに行くってことであるw 久しぶりにとんかつ屋のカツカレーを食べた。 それから、米がそろそろ切れそうだと思って職場の近くのスーパーに寄ってみたところ、宮崎県産の米があるのがおもしろいなと思った。 一足先に新米だから入れているのか、それとも通年で仕入れているのかはわからない。 ただ 5kg の無洗米はなく、別のスーパーに行ったら 2kg の宮崎産無洗米があったので買ってみた。 新米のくせに値引きされていて、どういうこっちゃ?

耳鼻科の駐車場にはいすが何個も置かれていて、発熱の人は今日は見かけなかったけど、発熱外来もやっているようだった。 先月頃は結構すごいことになっていたのかも知れないな。

%2 MS-DOS

MS-DOS のソースコードに出てくる XENIX というキーワード、Microsoft が開発していた UNIX なんだな。 8086 用の UNIX。 へぇ。 Microsoft としてはそれと互換性がある機能を MS-DOS に取り込んだというつもりだったのか。 確かに NUL 文字終端のファイル名指定やディレクトリの区切りに / を受け付けるあたりには Unix の影響は見えている。 /DEV/CON とか \DEV\CON とかって文字列が見えるのも XENIX 由来だな...

MS-DOS のメモリー管理はあまりよく覚えていない。 アセンブリ言語でいつも作っていたのは .COM 形式で、これは連続空きメモリーが全部確保された状態で開始される、だったはず。 なので別のプロセスを作成するにはメモリーを縮小する必要があって、realloc じゃないけどなんかそんなようなシステムコールがあったはず、とぼんやりと記憶していたが、SetBlock (4AH) というシステムコールがあるようだ。 Realloc とは違ってアドレスの変更は行わずサイズだけ変更するんだったと思う。

DEBUG.COM がどうやって EXE ファイルを読み込んでいるかは知らなかった。 ソースコードを見ると Exec システムコールを使っている。 全部準備するけど実行は開始しないというファンクションがあったようだ。

DOS にはプロセスの切り替えの概念があり、普通に Exec システムコール (spawn) を使えば実行中のプロセスは新しいものに切り替わる。 んで終了とか常駐 (メモリーに残したまま終了) とかすれば前のプロセスに戻る。 今のプロセスに関する情報は PDB ってのに保持されているみたい。 (これは何の略だ?) この PDB ってのはプロセス起動時のデータセグメントの先頭のようだ。 先頭に CD 20 (プロセス終了) があり、オフセット 80H にコマンドライン引数の長さ 1 バイト、81H からコマンドライン引数が入る。

んで、PDB を切り替える SET_CURRENT_PDB (50H) システムコールがある。 普通のプロセスにはまったく不必要なシステムコールだが、デバッガーなんかでは必要なわけだ。 実際 DEBUG.COM のコードには使っているところがあるが、実際に DEBUG.COM を立ち上げて PDB を調べたら DEBUG.COM のものになっていた。 あれ? と思ったら、引数に実行可能プログラムを指定して起動した時にはちゃんと起動したプロセスのものに切り替わっていた。

COMMAND.COM のソースコードを見ると、コメントにいろいろ書いてあった。 いくつかのパートにわかれていて、一部は上位メモリーに置いて、チェックサムを見て壊れていた時だけ読み直す、みたいなのがあるんだと。 常に使われていたかはわからない。 割り込み 22H (終了!?), 23H (Cntrl-C), 24H (fatal error), 27H (常駐) のハンドラーがあるんだって!? マジか、それシェルの仕事なのかw と思って検索してみたものの、27H まで COMMAND.COM だったのは 1.25 のほうじゃないかな... 2.0 の 27H の設定が見つからないんだが... あぁ、MSINIT.ASM にあった! 27H はシステムコールの一種として実装されているな。 極めて単純に新しいシステムコールに変換するだけみたいだけど。

こうしてソースコードを見ながら振り返ると、MS-DOS も恐ろしいほどブラックボックスとして扱っていた/扱われていたんだなと思う。 どうして COMSPEC に COMMAND.COM の代わりに設定するプログラムは現れず、シェルのヒストリ機能追加は KSH (KI-Shell) なり VZ Editor なり、常駐プログラムの形だったかというと、内蔵コマンドが多いし、結構いろんな裏仕事みたいなのがあって第三者は作りづらかったんだろうし。 デバイスドライバーを後から組み込むのは EO System が実現していたが、あれも何をやっていたかは知らない。 メモリー確保するか Exec システムコールで読み込んだ上で、どっからかデバイスドライバーの一方向線形リストの先頭を取り出してきて強引に追加していたのかなと思うと、よくそんなんで動いていたなぁという感じもする。 メモリー使用状況 (マップ) を出力するプログラムもあったな。 あれもどうやっていたんだか...

「常駐プログラム」の文化もすごかったな。 常駐後に制御したい・解放したい需要があり、それをみんな思い思いの方法で実装していた。 解放は最後に常駐したものから順に行わなければならず、順番を間違えると割り込みベクターを壊して動かなくなるという罠もあった。 壊すのは割り込みをフックして機能追加するというのが多かったためであり、あんなのも割り込みフックと常駐プログラムを管理するデバイスドライバーでも作ってみんなでそれを使っていたらもっと簡単になっていたかも知れないね。

2022/08/31 のコメントを読む・書く


prev, this, next

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

トップ / 日記索引 / 日記 (2022 年 8 月下旬)

Hideki EIRAKU