プログラミングの「は・て・な」

第1回 理想のコンピュータ×理想のプログラマ(?)
    〜流星号はマッハ15だからすごいんじゃない〜

長谷川裕行
2008/3/17

貴重な資源の節約が先決

 僕にとって理想の道具は、流星号やKITTのように人間の意思をムダなく正しく受け取ってくれる機械だった。もちろん、人工知能とか万能ロボットという意味ではない。人間がストレスなく事務処理を行い、望む結果を得られる道具──それがコンピュータなのだと、当時の僕はかなり固く信じていた。

 ユーザにとって親切なシステムを作るためには、いわゆる「冗長な処理」が必要だ。エラーメッセージにしても、いきなり「印刷できません」などと表示してはわけがわからない。プリンタのステータスを取得し、ユーザのわかりやすい場所に「プリント用紙がなくなりました」のように表示するべきである。できれば「プリンタにA4判の用紙をセットしてください」などとユーザが何をすればよいのかまで示すのが望ましい。

 それはわかっているのだが、当時のハードウェアはとにかくチープだった。CPUのクロックは8MHzで、メモリは256KB(MではなくKである)。時代とともに速度は向上し搭載メモリも増えていったが、それでも25MHzで640KB……といった具合である。

 ハードウェア上の制限から処理を少しでも速く済ませ、貴重なメモリを節約するのがプログラミングの基本であり、だらだらと冗長な処理を行うのはご法度。このトレードオフに悩んだものだ。

オーバーヘッドを省け!

 プログラムを作る側は、ムダなオーバーヘッドを省こうと直接VRAM(Video RAM)にデータを書き込んだりポートを監視してキーボード割り込みを処理したりするサブルーチンを作って、OSの機能をできるだけ使わずに済ませようとしたものだ。そのために、アセンブリ言語を多用した。

 プロファイラを使ってできあがったプログラムの処理速度を調べて、デバッガでムダなジャンプ命令やNOP(空命令)を削り、メモリにロードされるモジュールをコンパクトにすることも重要だった。骨格にはC言語を使っても、内部の関数の大半はアセンブリ言語で作ることが多かった。開発用の小さなツールは、全部アセンブリ言語で作ったりもした。そのほうが速くてコンパクトで、開発も楽だったのだ。

 当時のプログラミングでは、とにかく、メモリの消費を抑えて小さく速く作ることが至上命題だった。「コマンドまたはファイル名が違います」「どれかキーを押してください」など、OSの出すメッセージは簡潔すぎて初心者には意味不明だったが、それも速度向上とメモリ節約のためだったのである。ゆえに、一般ユーザにとってパソコンは「扱いにくい機械」だった。

すべてはユーザのために

 速さのために親切心を犠牲にしたわけだ。当時、コンピュータを扱う人間は研究者や開発者、あるいはマニアであり、コンピュータとは「そういうもの」だと知っていた。だから、簡潔すぎて不親切なメッセージにもとまどうことなく、十分に操作できたのだ。

 趣味で写真をやっていた僕は考えた。当時、カメラの技術ではすでに自動露光は当たり前で(現在のようなインテリジェントな測光ではなかったが)、ミノルタ(現、コニカミノルタ)がα7000で実現したオートフォーカスが話題だった。

 かつて、カメラは実に難しい機械だった。露出計で明るさを読み、適切な絞りとシャッター速度を決めなければならない。つまりユーザにやさしくなかった。それが、シャッターボタンの半押しで露出もピントも勝手に決まってしまうようになったのだ。

 自動機能のおかげで、写真技術が低レベル化したと嘆く人もいたが、逆にそのおかげでこれまでカメラを敬遠していた人が写真文化に携わるようになって、新しい表現が生まれたのも事実だ。

 目的は「道具を使って望む結果を得る」ことであって、基本操作の腕を競うことではない。もちろん、作る側は技術を競えばよいのだが、その技術は「使う側の利便」に寄与すべきである。

懐かしのアセンブリ言語

 そんなわけで、当時の僕は高速かつコンパクトなプログラムで、なおかつできるだけ親切なメッセージ表示をできないかと考え、テキストモードのウィンドウを使ったC言語用ライブラリをアセンブリ言語で作ったりした。当時“国民機”と呼ばれたNEC PC-98シリーズ用である。なにせ15年前(連載当時)のプログラムだから今では役に立たないが、ソースコードを少しだけ紹介しておこう(D_CON1.ASM、D_CON2.ASM、D_CON.INC。List 1はD_CON2.ASMの抜粋です)。

List1 PC-98シリーズ用テキストウィンドウ制御ライブラリのコードダウンロード
;----------------------------------------------------------------
; D_CON2.ASM -- ウィンドウ制御for PC-9801
;               Copyright 1990, H.HASEGAWA
;----------------------------------------------------------------

    DOSSEG
    .MODEL      COMPACT

INCLUDE         D_CON.INC

extrn           __xytoadr : NEAR

    .CODE

;----------------------------------------------------------------
; get_fk
;      ファンクションキーの取得
;      get_fk(int num, char *buf)
;      *buf : 16*10bytes

BEGIN     _get_fk
          ARG       num:WORD, buf:PTR
          push      bp
          mov       bp, sp
          push      dx
          push      ds
          mov       cl, 0ch
          mov       ax, [num]
          lds       dx, [buf]
          int       0dch
          pop       ds
          pop       dx
          pop       bp
          ret
_get_fk   ENDP

;----------------------------------------------------------------
; put_fk
;      ファンクションキーの設定
;      put_fk(int num, char *buf)
;      int num;
;      *buf : 16*10bytes

BEGIN _put_fk
          ARG       num:WORD, buf:PTR
          push      bp
          mov       bp, sp
          push      dx
          push      ds
          mov       cl, 0dh
          mov       ax, [num]
          lds       dx, [buf]
          int       0dch
          pop       ds
          pop       dx
          pop       bp
          ret
_put_fk   ENDP

;================================================================
; _w_open は画面の情報をバッファへ保存し,_w_close はバッファの
; 情報を画面へ出力します.はっきり言って,ただそれだけです….
;================================================================

;----------------------------------------------------------------
; _w_open
;    _w_open(start, words, wdw->org_txt, wdw->org_atr);

BEGIN __w_open
          ARG       start:WORD, words:WORD, txt:PTR, atr:PTR
          push      bp
          mov       bp, sp
          push      ds
          push      es
          push      si
          push      di
          mov       ax, T_VRAM0
          mov       ds, ax
          mov       si, [start]
          mov       cx, [words]
          les       di, [txt]
          rep       movsw
          mov       ax, A_VRAM0
          mov       ds, ax
          mov       si, [start]
          mov       cx, [words]
          les       di, [atr]
          rep       movsw
          pop       di
          pop       si
          pop       es
          pop       ds
          pop       bp
          ret
__w_open  NDP
...(以下省略)...

 テーマから外れるのでソースの解説は割愛する。それにしても、アセンブリ言語のソースを見るとコーフンしてしまうのはナゼだろう? ついつい、ソースを目で追って解読しようとしてしまうのだよ(笑)。ソースの可読性については、『3日もたてば自分も他人』といわれるくらいである。15年もたてばいったいどんなものか? もう別世界の人間のようになっているのではないか……と、思ったのだが、これが読めちゃうから、アセンブリ言語はおもしろい(昨日作ったVC++のソースは、ときどき自分でも読めないことがあったりする(^^;ゞ)。

 それにしても、僕もアセンブリ言語から離れてずいぶんたつ。今では、C++やVBやSQLがもっぱらの相手である。Windowsが標準的なプラットホームになり、アプリケーション開発は既存の(処理系に予め用意された)ライブラリやコンポーネントをいかに合理的に組み合わせるかが重要になった。時代が変わったなぁ、とつくづく思う。

 なお、D_CON1.ASMとD_CON2.ASMはボーランドのTurbo Assembler(TASM)用のコードで、Turbo-Cから利用するライブラリとして作ったものの一部である。このほかに記号定数とマクロを定義した定義ファイルD_CON.INCが必要だ(今や、実用にはなりません)。

 これら3つのファイルは、最終的にC言語のソースから呼び出される関数を定義している。そのため、これらを扱うためのC言語の.hファイルなども必要になる。

ハードは進化したけれど

自分戦略研究所、フォーラム化のお知らせ

@IT自分戦略研究所は2014年2月、@ITのフォーラムになりました。

現在ご覧いただいている記事は、既掲載記事をアーカイブ化したものです。新着記事は、 新しくなったトップページよりご覧ください。

これからも、@IT自分戦略研究所をよろしくお願いいたします。