S 耐ⅷ 4 はしめに PROM の書き込み コンヒ。ュータの発達の速さには目ざまし いものがあり , 現在 , 私たちの身の回りに もマイコンを搭載した製品が広範囲に普及 しています。 パソコンはもちろん , カメラ , 家電製品 , 車 , 電話 , ワープロなど , マイコンを搭載 した製品は多品種化が進んて、います。これ らの製品には , マイコンを動かすためのプ ログラムが必要て、す。プログラミング用媒 P OM のノヾッケージの種類 マイコンを搭載した製品も「軽薄短小」プ ームのもとて、 , より軽く , より小さくする ことは製品開発の中て、も不可欠な要素にな っています。 パソコンも , デスクトップからラップト ップを経て , ノート ( ブック ) 型に移行しつ けされます ( TabIe 3 ) 。 佐藤文昭に = ナトエレクトロニクス ) つあります。製品の小型化への要望は部品 登場しパッケージの多品種化が進んて、いま ッドチップキャリア ) などの PROM が市場に ップキャリア ) , PLCC ( プラスチックリーデ ンラインパッケージ ) , LCC ( リードレスチ クノロジ ) 化した基板用の SOP ( スモールオ 近年て、は , SMT ( サーフェイスマウントテ 上により , 小型化する傾向にあります。 が主流だった PROM も , IC の実装技術の向 の小型化を推進し , 数年前まて、は DIP タイプ す (Fig. 1 , Fig. 2 ) 。 体としては , フロッヒ。ー ードディスク , TabIe 1 ROM ROM の種類 MOS CD-ROM などの外部記憶媒体と ROM, PLD などの IC 記憶媒体とに大別されます。 今回は , プログラミング媒体の中て、 PROM を中心に どのようにしてシステムプログ ラムを書き込むかについて説明します。 P OM の種類 ROM の種類は Table 1 のように分類され ます。 ROM ( リードオンリメモリ ) は読み出し専 用のメモリて、すが , ューザが自らプログラ ミングて、きる機能をもった ROM が PROM( プ ログラマプルリードオンリメモリ ) て、す ( Table PROM は , プログラミングが 1 回しかて、き ないバイボーラ PROM, 何回もプログラミ ング可能な EPROM ( イレーザプル PROM), EEPROM ( エレクトリックイレーザプル PROM ) に分類され , 目的にあわせて使い分 76 CMAGAZINE 1990 11 N M OS CMOS アクセス スピード 中速 中速 高速 消費電力 中 小 大 メモリ容量 中 大 TabIe TabIe 2 バイボーラ ROM の種類と機能 種類 PROM ROM 3 マスク ROM PROM の種類と用途 PROM 種類 EPROM EEPROM ノヾイボーラ PROM 機能 書き込み可能 書き込み不可能 用途 大容量ていちばん使われている オンボード用中心 高速処理 , 軍事用など中心
新 MS - DOS プログラミング入門 , , プロラマのたの Fig. 5 標準入力をリダイレクト中のキー入力 標準入力 ( 八ンドル 0 ) を退避 別の CON テパイス ( たとえば標準工ラー出力 ) 標準入力 ( 八ンドル 0 ) を元に戻す 標準入力 ( 八ンドル 0 ) からキー入力 を標準入力 ( 八ンドル 0 ) に割り付け TabIe 2 IOCTL データの取得 DOS ファンクション 4400h IOCTL データの取得 引数 返り値 機能 = 44h = 00h = ファイル八ンドル キャリー = 0 キャリー INT 21 h BX AL AH DX : テパイステータ AX=06h : 無効な八ンドル AX = 01h : 無効なファンクションコード ピット 7 = 1 : 八ンドルはテノヾイス , = 0 : ファイル 八ンドルはファイルを表す。 デバイスデータのビット 7 が 1 の場合テパイスを表し , 0 の場合 BX レジスタで指定する八ンドルのテパイステータを取得する。 TabIe 3 isatty 関数 テパイスのチェック int isatty(handle) ・ = 0 : キャラクタテパイス以外 返り値 ! = 0 : キャラクタテパイス オープンずみのファイル八ンドル int handle , トしていても , 1 画面分表示したところてキ ー入力待ちになります。この原理をちょっ と考えてみましよう。 これは今まてに説明してきたことの応用 て、解決て、きます。すなわち , Fig. 4 , Fig. 5 に示すように標準入力を退避しておいて , 標準入力に別の CON デバイスを割り付け て , 標準入力からキー入力を行えば , ファ イルからてはなくキーポードから入力され ます。キー入力が終わったら標準入力を元 に戻しておけばよいわけて、す。 これをプログラムにしたのが List 4 て , 簡 単な MORE コマンドの実例てす。ここては 手を抜いて標準工ラー出力を割り付けてい ますが , 本当は CON デバイスを改めてオー プンして割り付けるのがよいかもしれませ ん。 List 4 て ESC シーケンスを使用しています のて、 , ついて、に Table 1 に ANSI ESC シーケ ンスをまとめておきます。 ESC シーケンス を使用される場合はて、きるだけ機種依存を 避けたものを使用されることをお勧めしま す (ESC シーケンスを使用することじたいに オーバヘッドがありますから , たとえば画 面消去に ESC C2J ESC * のどちらを使用しても動作速度はほとんど 変わりません。それなら , 動作する機種の 多い ESC [ 2J を使用するのが賢明だと思い ます ) 。 リダイレクトの確認 標準入出力がファイルにリダイレクトさ れているかどうかを確認するには DOS ファ ンクション 4400h ( Table 2 ) の IOCTL データ の取得を使用します。このファンクション の返り値の DX レジスタのビット 7 が 1 の場合 デバイスを表し , 0 の場合ハンドルはファイ ルを表します。 C 言語て、は Table 3 の isatty 関 数を使用してこのことを判定することがて、 きます。 新 MS-DOS プログラミング入門 101
0 「 m 面 on from (ompiler ma 「 5 シス弘・ワン Power Ctrace Power Ctrace を 使用した効果的な テパッグ Power Ctrace ( 以下 PCT) を使 用して C プログラムをデバッグした 場合の利点について説明します。 PCT の提供している機能は , ほ かのソースレベルデノヾッガと大差 ありませんが , 高性能な機能を簡 略な操作て、提供し , デバッグ時の 負担を軽減している点に特徴があ ります。 基本的にキーひとつの入力て、操 作がてき , ウインドウごとにまと められた簡易ヘルプ画面を参照す ることて , 操作方法を容易に理解 て、きるようになっています。 こては PCT の機能のうち , よ く使用するものについて述べてお きます。 複数ウインドウの 同時表示 PCT て、は , Table 1 に示す 8 種類 のウインドウから , 同時に 4 つまて のウインドウを表示てきます。 のほかにコマンドキーの一覧を表 示するヘルプ画面があります OPCT 全体にわたる共通コマンドのヘル プ画面と , 現在選択されているウ インドウの固有のコマンドのヘル プ画面とがあり , それぞれファン クションキー亘 , て、表示 されます。 PCT< は , デバッグ時の状況に 応じた適切なウインドウを選択す ることにより , 必要な情報が瞬時 に得られ , デバッグ効率が高くな ります。 たとえば , ソースウインドウ , 出力ウインドウ , 変数ウインドウ を表示すれば , プログラムの流れ を追いながら , プログラムの進行 に伴って変化していく変数の内容 や標準出力画面のようすを確認て きます。 変数の自動表示 / 階層化表示 変数ウインドウては , 使用され ている変数の内容を自動的に表示 します。このため , 変数の名称や 型を覚えておく必要はなくなりま す。 変数ウインドウて表示する変数 には 2 種類あり , ローカル変数とグ ローバル変数に分けられます。ロ ーカル変数は関数ごとに固有なた め , トレースの対象となる関数に 応じて随時変わります。グローバ ル変数は , あらゆる場所から参照 可能なため , 常時表示されていま す。 とくに注目している変数や , 変 数ウインドウのサイズと表示順序 により常時表示てきない変数につ いては , ウォッチウインドウに登 録することにより , 常時参照可能 となります。 また , PCT て、は , ポインタや配 列 , 構造体などについては , 変数 の内容を展開して , さらに詳しい 情報を表示させることがてきます。 この機能により , 変数の個々の要 素をすべて見ることがて、きます。 プレークポイントの 多目的利用 PCT て、のトレースには , 1 ステッ プ実行 , トレーススヒ。ード実行 , フルスヒ。ード実行の 3 つの方法があ ります。このうちトレーススヒ。ー ド実行 , フルスヒ。ード実行ては特 定の場所に到達したり , 特定の条 件を満した場合には , 実行が停止 します。 前者のように , 実行を停止させ るために指定する場所をプレーク ポイントといいます。プレークポ イントは Table 2 て、示す場所に設 定することがて、きます。 プレークポイントは , チェック 済みの部分を飛ばしてトレースし たい場所に移動する場合や , 関数 呼び出しやループて、特定の回数だ け実行してみるといった場合に使 用されます。なお , プレークポイ ントの設定数には制限がありませ ん。 後者のように , 実行を停止させ るために指定する条件をウォッチ ポイントといいます。ウォッチボ イントとして設定てきる条件は , Table 3 に示すものが挙げられま す。 ウォッチボイントては , プレー クポイントと同様に特定の場所ま てスキップしたり , 特定の変数や メモリの内容に注目しながら実行 を止め , 条件成立時の状況を解析 などに使用されます。 なお , ウォッチボイントは最大 32 個まて、設定することがてきます。 TabIe 1 表示可能なウインドウの種類 1 2 3 4 5 6 7 8 ソースウインドウ 出力ウインドウ 変数ウインドウ ウォッチウインドウ メモリウインドウ シンボルウインドウ アセンプラウインドウ 87 ウインドウ C のソースコードを表示 プログラムの標準出力画面を表示 変数の値を表示 ウォッチボイントの設定状態を表示 メモリの内容を表示 外部変数 , 関数のアドレスを表示 逆アセンプルを表示 8087 / 287 の状態を表示 Table 2 プレークポイントの設定場所 1 C ソースコードの 1 ステップ ( ソースウインドウ ) 2 アセンプリコードの 1 命令 ( アセンプラウインドウ ) 3 関数のエントリアドレス ( シンホルウインドウ ) TabIe 3 ウォッチボイントの設定条件 1 2 3 変数の監視 ( 変数ウインドウ ) メモリの監視 ( メモリウインドウ ) 実行状態 ( 実行カウンタ / 関数の深さ ) の監視 lnformation from Compiler Makers 155
まて、の引数て、す。対象となる引数は Table 1 スタックが使われます。 きい番地 ) になります。 て、示されるレジスタに割り当てられます。 関数のリターン値は , 大きさが 1 バイトな 呼び出された関数は SP レジスタを破壊し レジスタに割り当てられなかった引数は らば A レジスタに , 2 バイトならば HL レジス てはいけません。それ以外のレジスタは呼 スタックにつまれて渡されます。 タに , 3 バイト以上ならばスタックにつまれ んだ関数が必要なレジスタを待避するのて、 , また , printf() 関数のような可変パラメタ て返されます。関数値がスタックにつまれ 破壊してもかまいません。したがって , ア 関数の場合には引数の受け渡しにはすべて る場合 , その場所はすべての引数より下 ( 大 センプリ言語のプログラムから C の関数を呼 び出す場合には必要なレジスタを待避して から , C の関数を呼び出さなければいけませ ん。 ところて、 , コンパイラは関数や外部変数 〃 ( アンダースコア ) を付加 の名前の後に します。したがって , アセンプリ言語て、関 Fig. 2 List4 をコンバイルした結果 CSEG PUB い C table ta b 1 e ・ 66 DW DB DW DB DW DB DW DB DW DB DW DB DW DB DW lSt tblentr•y 1 : typedef 2 : 3 : 5 : 6 : TBLENTRY 7 : 8 : 9 : 14 : 16 : TBLENTRY struct Char int TB し ENTRY; table[] 0 1 2 3 4 5 6 7 っ乙《 0 ー 8 0 ^ 0 1 よ CD ワレれ 0 っ行ー行ー戸 0 ーれ 0 ー *tblp; ・呼び出す側 (C) asm (char, long) : int, abc; int / * プロトタイプ宣言 * / int int VO i d DSEG PUBLI C tblp- 2 DS tblp- ・ , 1 , 0X12345678 ) : . 3 List7 から生成されたコード Fig putch PUSH PSW 0 ANI 1 JZ 2 POP PSW OUT 1 RET ・呼び出される側 ( アセンプリ言語 ) : C 言語で asm ( ) を呼び出せるように宣言。 pub lic asm : C 言語で定義した外部変数を参照することを宣言。 abc extrn long l); asm(char C, int i, int 引数 c は A レジスタに i は DE レジスタに ーはスタック CSP 十 2... SP 十 5 ] にセットされて渡される。 ret urn 値は H しにセットしなければならない。 asm TabIe 1 : SP 以外のレジスタは破壊してもよい。 ; return 値を H しにセットして ret する。 1 番目 2 番目 3 番目 A E DE BC 大きさ 1 バイト 2 バイト ret 特集 ROM 化プログラミング考察 73
List 3 域とデータ領域を , RAM に BSS 領域を割り 当てるだけのことて、ある。その際に , 0 以外 て、初期化されているデータについてリテラ ルにしてしまう必要があるのもミニマムモ デルの場合と同様て、ある。 また , 0 以外に初期化されているデータ を , スタートアップ時に ROM から RAM へ 読み込むという方法もある。この方法のよ いところは , 前述したとおり , プログラミ ングて、とくに気を使う必要がないことて、あ そして , この方法も ( ROM と RAM の容量 を気にしなければ ) 実現は , わりと簡単て、あ る。つまり , データ領域を RAM に割り当 て , スタートアップ時に ROM からロードす ればよいのて、ある。 それは , たとえば , mov # 0X6000 , 「 4 mov # datalo, 「 5 69 : rdr; *rnext 十十 if (&rbuf[sizeof rbuf] くニ rnext) 70 : rnext = rbuf; ー 0X40 : 72 : ssr & = 74 : 75 : @port void txi ( ) 76 : if (tdone = tnext) 77 : return: while (!(ssr & 0X80 ) ) 80 : tdr ニ *tdone 十十 : if (&tbuf [sizeof tbufJ くニ tdone) 82 : 83 : tdone tbuf : ー 0X80 : 84 : ssr & ニ 85 : / * TDRE * / 割り込みべクタテープル ( ebvec. c ) S , よワ 3 っ 0 ・ 4 ・戸 0 C.D 0 ー 8 0 ) . 0 0 0 0 0 0 0 0 Q. a. Q. a. 1 ーワ 0 00 ・ 4 ・戸 0 ( 0 ー 8 0 1 人 -4 ・ - -0 ^. 0 ー 0 1 よ C'O っ 0 、 4 ・ ( 0 0 ー 8 cmp # datahi, 「 5 bcc L4 mov @「 4 十 , 「 3 mov 「 3 , @「 5 十 bra L3 といったプログラムをスタートアップ中に 付け加え , この例て、はデータ領域を 0X6000 番地から ROM に焼き付けておくのて、ある。 そうすることにより , スタートアップ時に 本当のデータ領域にその初期値がロードさ れるというわけて、ある。 TabIe 1 オプジェクトフォーマットトランスレータ 味 意 インテル HEX , テクトロニクス拡張 HEX , モトローラ S レコード HP ー 64000 オプジェクトモジュールフォーマット ( HP ー OMF ) ESROFF フォーマット COFF フォーマット ソフィアシステムアプソリュートフォーマット ( SAOF ) 0xff7f 番地まて、なのて、 , このような配置にし そま、の てみた。 RO イの方法 図て、表すと Fig. 3 のようになる。 これを見てわかるように , データ領域は 最後にマキシマムモードて、の ROM 化につ 生成されなくなっている。 以上 , 駆け足て、あったが , H8 / 500 を題材 Fig. 2 て、 link の次にある hex というのは , いて簡単にふれておくことにする。 に , C プログラムの ROM 化を中心に述べ ニマムモードて、の例を挙げ 前節て、は , この場合 , モトローラ S レコードに変換する ためのユーティリティて、ある。このほかに たが , マキシマムモードて、もそう大差はな 説明不足の点も多かったかと思うが , 多 も Table 1 に示すように , いろいろなオプジ く , ー x4 て、コンパイル ( すなわち関数がテキ 少なりとも読者諸氏の参考になれば幸いて、 ェクトフォーマットに対応している (Table スト領域 , リテラルがデータ領域 , 0 初期化 ある。 1 参照 ) 。 データが BSS 領域 ) し , ROM にテキスト領 62 CMAGAZINE 1990 11 名称 h ex tOhp ts ro 幵 tcoff tosaof さしま
リニアサーチとバイナリサーチの計算量の比較 TabIe 1 リニアサーチ ことを示すものて、す。たとえば , も しデータが ( 文字列などへの ) ポインタて、あ れば , データがセットされていない 挿入の計算量 ( 1 回当たり ) 示すのに NULL を使うのが自然て、しよう。 さて , 話をもとに戻しましよう。たった 探索の計算量 ( 1 回当たり ) 今考察したケースて、は , キーが 0 ~ 99 の整数 削除の計算量 ( 1 回当たり ) て、ある , という前提に立っています。しか n は , 表に登録するテータの個数とする し , これはあくまて、も説明をするための人 為的な設定て、 , 現実には , キーをそのまま て、す。 するデータ構造として , 配列の代わりに連 配列の添え字にて、きるのは稀て、す。 ある特定の範囲内に収まる整数 ( 0 ~ 99 と 結リストを使うこともて、きます。リニアサ そこて、 , キー x の値を配列の添え字へと写 しましよう ) をキーにもつ一連のデータがあ ーチは , 線形探索とも呼ばれます。 像する関数 h ( x ) を導入します。この関数をハ るとします。また , 話を簡単にするために バイナリサーチ (binary search) は , あら ッシュ関数 (hash function) と呼びます。ま キーの重複は許されないことにします。 かじめ配列内にデータをキーの昇順に並べ た , ハッシュ関数が返す値をハッシュ値 ( hash のデータを表に登録して , 探索を行うこと ておく方法て、す。探索するには , まず探し value ) といいます。ハッシュ ( hash ) とは , も 出したいキー x と配列の中央の要素のキー y を考えます。 ともと「 ( 肉などを ) 細かく切り刻む」という この場合 , もちろんリニアサーチやバイ とを比較します。 x = = y なら探索は成功て 意味て、す。つまり , キーの値を「切り刻む」 ナリサーチを使うこともて、きます。しかし , す。もし , x < y なら目的の要素は配列の ことによって無理やり配列の添え字にして キーが特定の範囲に収まる整数て、あること 前半にあるはずなのて、 , 探索する範囲を配 しまうわけて、す ( ちなみに , ハヤシライスの を利用すれば , きわめて効率よく処理する 列の前半にして , 再び比較から繰り返しま ハヤシは hashed beef の hashed が訛ったもの ことがて、きます。大きさ 100 の配列 x を用意 す。また , x > y なら目的の要素は配列の して , キーの値 a をこの配列の添え字としま て、す ) 。 後半にあるはずなのて、 , 探索する範囲を配 さて , ハッシュ関数 h ( x ) を用意すれば , キ す。つまり , キーが 0 のデータは x CO] に 列の後半にして , 再び比較から繰り返しま ーの値に応じて配列にデータを格納するこ キーが 37 のデータは x [ 37 ] に というぐあ す。探索する範囲がただひとつの要素にな とがて、きます。データを格納する配列 tab いに対応させるわけて、す。この方式をとれ ってもキーが一致しなければ探索は失敗て、 があるとすると , キ—a をもっデータは配列 ば , 挿入 , 探索 , 削除ともに O ( 1 ) て、て、きる す。 の要素 ta e [h(a)] にセットされます。 ことは明らかて、しよう。 バイナリサーチて、は , 1 回比較を行うたび ッシュ関数として計算量が O ( 1 ) のものを選 こて、 , もう少し細部をつめておきまし に探索の範囲が半分になるのて、 , 10g2n 回程 ぶようにすれば , 挿入 , 探索 , 削除ともに よう。配列の各要素について , データがセ 度の繰り返して、探索を行うことが可能て、す。 O ( 1 ) て、実現て、きることになります。 ットされているかどうかを区別する仕組み バイナリサーチは 2 分探索とも呼ばれます。 , こて、 , データを格納する配列をハッシ が必要になります。これには , ふたつの方 リニアサーチとバイナリサーチの比較を 式が考えられます。 Table 1 に示します。 TabIe 2 ハッシュ値 ( List 1 の hash( ) 関数を ひとつは明示的にフラグをもたせる方式 使って八ッシュ値を求めた ) て、す。たとえば , 次のようにします。 八ッシュ法の原理 文字列 八ッシュ値 struct { occupied ; int one ハッシュ法は , データの個数によらずに two DATA your data ; three 挿入 , 探索 , 削除の操作を実質的に O ( 1) ー four こて、 , メンノヾ occupied はデータがセット ーっまり一定時間一一イ、行えるすぐれたデ five されているかを示すフラグて、 , 0 以外て、あれ ータ構造て、す。ハッシュ法の原理は , リニ SIX ばデータがセットされています。 アサーチやバイナリサーチとは根本的に異 seven eight もうひとつは , 明示的にはフラグ なるものて , キーの値と , データを格納す をもたないものて、 , データとして決して現 る位置 ( 配列の添え字の値 ) を直接に関連づ ten れない値によって , データがセットされて けてしまう , というのが基本的なアイデア ノヾイナリサーチ O(n) O(log2n) O(n) 0 ( 1 ) O(n) O(n) つ」 6 6 4 6 0 5 9 6 「 / 2 4 3 4 2 4 4 2 2 2 80 CMAGAZINE 1990 11
ニ ~ ッ第一 1 あまりよい選択とはいえない ICE 用のフォーマットは lntel OMF-86 が 一般的だ。このフォーマットに対応した ICE の購入を勧める。ただし OMF ー 86 フォーマッ ト中のすべてのデバッグ情報を ICE が有効に 使用していないものがあるのて、確認が必要 TabIe 2 V25 ボードのメモリ配置例 アドレス 00000 00400 10000 F0000 F F F FO 内 谷 割り込みべクタ 変数領域 メモリの存在しない領域 ROM 領域 リセットアドレス て、ある。この出力ファイルを ROM 化するに デヾッグ情報サポート範囲 はターゲットボードのメモリにあわせて , クラス単位て、再配置しなければならない TabIe 2 は , 一般的な V25 ポードのメモリ配 デバッガを使うにはデバッガが理解する ランタイムライプラリのサポート 置例て、あるが , これを LOCATE に教えるの デバッグ情報をコンパイラ , リンカ , ロケ ータを通じて出力ファイルへ書き出さなけ がコンフィグレーションファイル (List 1 ) の スタートアップコードの中て、は , ランタ ればならない。現在 , 標準的なデバッグ情 役割だ イムライプラリのサポートのために専用の CLASSi•ィレクティ 7+(TabIe 3 参照 ) 報として OMF-86, CodeView, Borlandi• 関数・変数が設定されている。これがない バッグ情報の 3 つがある。低価格ロケータの て、 , クラス単位て、特定のアドレスに割り付 と , たんに C プログラムのコードを ROM 化 中にはマップファイルの情報しかデバッグ けを行っているが , 重要な区分は ROM と するだけて℃プログラマが当然使用可能と考 情報として扱えない製品があるのて、注意し RAM て、ある。それぞれに割り付ける最初の えるライプラリがまったく使用て、きない たい。この場合には , C プログラムの static ( ) クラス名だけを CLASS ディレクテイプて、指 ロケータの購入に際しては , 実際にどの関 定し同グループ内の後続のクラスは〇 RDER 関数や変数は見えない ( アドレスが不明 ) 。 ディレクテイプて、連続指定する。 R 〇 M ディ レクテイプて、は , 出力ファイルに含めるク ラスだけを指定する。 RAM の変数領域 ( ク ラス BSS) はアドレスを割り付けるだけて、 , 浮動小数点演算はある種の制御機器て、は ファイルには何も出力しない。初期化デー LOCATE ノヾッケージの中身 必須だ。とくに AD 変換などを行った場合 タ ( クラ幻 NITDATA ) は ROM へ出力するの に , 整数演算だけて、は桁不足になることが は当然だ。 今回使用した Paradigm LOCATE'€ッケ 注意が必要なのは , グループ内のクラス ージには , LOCATE. EXE, HEXFMT. MS-C と Turbo C に付属の演算ライプラリ の順序は , マップファイルの生成したとお EXE, SYSDOC. EXE の 3 つの実行ファイル は ROM 化可能て、ある。このサポートもスタ りにしなければいけないことだ。なぜなら , がある。 LOCATE は標準て、 OMF ー 86 を出力 ートアップコード中にあるはすだ。 生成されたインストラクション中のオフセ し , HEXFMT が HEX フォーマットへ変換 ットアドレスはグループの先頭からのオフ メモリモテル する。 SYSDOC はターゲットのメモリ構成 セット値だからだ。 を自動的にドキュメント化するプログラム List 3 が LOCATE の出力したファイルの メモリモデルは , タイニメモリモデルを だ (Fig. 1 参照 ) 。 セグメントマップて、ある。出力コードはす 除いて , すべてをサポートしてしかるべき List 2 は Turbo C のリンカ TLINK が出力 べて絶対アドレスに変換されていることは だが , サポートしていない製品もある。 した map ファイルて、標準的なメモリマップ 最終結果て、ある HEX ファイルを見ないとわ 特集 ROM 化プログラミング考察 65 ロケーションスピード ロケーションは , 本来 , さほど時間のか かるソフトて、はないのて、 , 実行時間に関し てあまり心配する必要はない 部のロケータは驚くほど時間がかかるのて、 注意が必要だ
五ロ はじめて学ぶ 0 プログラミング 第 14 回高木聡 / 山崎信行 標準ライフラリ関数の使い方 3 前号では , ファイル操作に関する標準ライプラリ関数を取り上げました。今 回も引き続き , ファイル関係の関数について勉強します。前号で紹介できな かった関数について , 多少長めのサンプルプログラムを用いて解説します。 にプロック転送し , 配列 s を文字列として扱 進めることになります。 うためのものてす。 関数 fseek を用いたプログラム例 17 行目はファイルの先頭位置にシークし ています。この場合ファイルをオープンし それては ,List 1 を見てください。このプ それては , 復習を兼ねて簡単な例から始 た直後なのて , ファイルポインタは先頭位 ログラムは listl. dat(List 2 ) というファイル めましよう。まず , 関数 fseek を用いたプロ 置にあります。つまり , 実際には何もして をオープンし , ファイル内をシークしなが いないのと同じてすね。 18 , 19 行目はシー グラムを作ります。 らその内容を表示するものてす。 11 行目て クに成功したときの処理てす。この 2 行の実 関数 fsee k [ ヘッダファイル ] listl. dat というファイルをバイナリファイル 行には 17 行目の if 文の式を ! fseek ( ・・・ ) とする 読み込みモード感「 b 〃てオープンしていま [ 書式 ] 必要があります。なぜなら fseek はシーク成 す。 16 行目て読み込み用のバッファ (char 型 功時に 0 を返す関数だからてす ( if 文の式の真 int fseek( FILE * stream, の配列 s ) の最後の要素 s [ MAX ] にヌルを long offset, int origin ) ; と偽の処理を思い出してください ) 。 代入しています ( s は , 9 行目て MAX 十 1 要 この関数は , 0 「 igin の位置から offset< 指 18 行目ては , 関数 f 「 ead を用いて cha 「型の 定されたバイト数だけファイル位置を移動 素の配列として宣言してある ) 。この処理は 配列 s にプロック単位て MAX バイト読み込ん します。この動作のことを一般に感シーク〃 関数 f 「 ead を用いて MAX 個のデータを配列 s ています。 19 行目てその配列 s を出力してい と呼びます。関数の戻り値は , シークに成 関数 fseek を用いたプログラム例 功すれば 0 を返し , 失敗すれば ! 0 を返しま す。 origin には , Table 1 のようなマクロが 用意されています。 たとえば , fin を日 LE 型のポインタとし , 以下のようにします。 fseek( fin, 100L , SEEK_SET ) ; これは , ファイルの先頭位置から , 100 バ イト移動した位置にファイルポインタ fin を TabIe 1 origin に指定できるマクロ 意味 ongln ファイルの先頭位置 SEEK—SET ファイルの現在位置 SEEK—CUR ファイルの末尾位置 SEEK—END stdio. h List 1 1 : # i ncl ud e く std i 0. h> 2 : # i nc lude く std ⅱ b. h > 3 : 4 : #define MAX 5 : 6 : void main( void ) 8 : F I LE *f i n : cha r s [ MAX + 1 ] : 9 : if ( ( fin ま fopen( "listl. dat". fprintf( stderr, ”ファイル %s がオープンできません。 Yn ” ex i t ( 1 ) : 14 : 15 : 20 : 22 : / * 関数 fread の要素数 * / 5 = NU しし ) { / * ファイルオープン * / "listl. dat" ) : / * 文字列の終わりを表す。 if( !fseek( fin, 0 し SEEK-SET ) ) { fread( s, sizeof( char ) . MAX, fin ) : printf(" ファイルの先頭位置から if( !fseek( fin, 5 し SEEK_CUR ) ) { fread( s, sizeof( char ) , MAX, fin ) : % 2d 文字出力・ %sYn", MAX, s ) : 122 CMAGAZINE 19 11 ファイル操作 2
ようにします。たとえば , 「文字列の 1 文字 個 , 90 % のとき 5.5 個のバケットを調べる必 ンダム」に選択するようにすれば塊の発生を 要があります。また , 「ランダムな数列によ 目をそのままハッシュ値とする」というのも 防ぐことが可能てす。これを実現するため ってバケットを調べる」方法ては , 使用率が 立派なハッシュ関数には違いありませんが , には , 1 から B ー 1 まての数が必ず 1 回だけラ 80 % のとき 2.0 個 , 90 % のとき 2.6 個となり それよりは List 1 のように「すべての文字コ ンダムに出現する数列 nl , n2 ・・・・・ nB ー 1 を用意 ードの和をハッシュ値とする」というほうが ます。 しておいて , よいてしよう。また , 「キーの値を 2 乗して この結果から , 大まかにいって , 前者て hk (x) (h(x) 十 m) mod B その中央をとる ( 平方採中法 ) 」という方法に は 80 % , 後者ては 90 % が最大使用率の目安 とします。たとえば , 10 個のバケットがあ よって , ランダムな値が得られることがし と考えられます。このリミットを越えてデ るハッシュ表に対して , ータを登録すると , 調べるバケットの個数 られています。 6 , 1 , 4 , 7 , 2 , 9 , 8 , 3 , 5 は急激に増加して , 探索時間は一定とみな という ( ランダムな ) 数列を用意します。ハ ッシュ値 3 をもっキーに対しては , 次の順番 せなくなります。 ハッシュの応用 てバケットを順に調べます。 ハッシュ関数 ところて , ハッシュという概念は表の探 同様にしてハッシュ値 1 をもつキーに対し 索以外にも応用することがてきます。大き ては , チェイン法て、もオープンアドレス法ても , なデータを , 大量に比較するような場合 , 7 , 2 , 5 , 8 , 3 , 0 , 9 , 4 , 6 ・・・・・・ ( b ) ハッシュ法を応用して処理時間を短縮する ハッシュ関数が均等なハッシュ値を発生す となります。ここて , 再ハッシュ系列 ( a ) て ることを前提としています。ここていう「均 ことがてきます。 はバケット 7 の次はバケット 0 になりますが , あらかじめ各データのハッシュ値を計算 等」とは , すべての可能なキー値を対象とし 再ハッシュ系列 ( b ) によればバケット 7 の次は しておきます。そして次の手順て比較を行 たときに , ハッシュ値が均等に等確率て、生 バケット 2 になります。このように , バケッ います。まず , ハッシュ値を比較して , も 成される ( 静的に均等 ) だけては不十分て、す。 トが衝突したとしても , 次に選択されるバ しハッシュ値が等しくなければ , この時点 実際には , すべてのキーの値が等確率て、出 ケットが別なのて、 , 塊がてきる現象を回避 て , ふたつのデータの値は異なっているこ 現するわけて、はなく , キーの値はかなり偏 てきます。 とがわかります。ハッシュ値が等しければ , オープンアドレス法の データ本体が等しいかどうかを比較します。 キーとして実際に出現する値に対して , ハ 解析 ッシュ値が均等に振り分けられる ( 動的に均 この方法ては , ①データが等しい 等 ) ことが望まれます。 ②データは等しくないが , たまたまハ プログラム中の変数名を考えると , al, オープンアドレス法の解析は難しいのて , ッシュ値が一致した ・・といった系統的な変数名を使用する 計算の過程を省いて結果だけを Table 3 に示 a2 ・・ という場合にかぎって , データ本体の比較 のはよくあることて、しよう ( こういった無機 しましよう。詳しくは , 参考文献 [ 1 ] [ 2 ] が行われます。てすから , ほとんどの場合 的な変数名のつけ方は , 悪いプログラミン を当たってください グスタイルて、すが , ここて、は例として考え にデータが等しくないようならば , ハッシ TabIe 3 は , 探索を行ったときに平均する ュ値の比較だけてすむのて、処理時間が大幅 てください。また , プログラムを自動生成 と何個のバケットを調べなければならない するようなツールは , 通常このような名前 に短縮されます。 かを , ハッシェ表の使用率の関数として表 ところて、 , この手法は , 計算量のオーダ を発生します ) 。たとえば , 先ほどの List 1 しています。また , この表て、は , 探索が成 ーを下げずに , たんに定数係数を下げるだ て示したハッシュ関数ては , al と a2 , a12 と 功したとき ( データが見つかったとき ) と探 けのいわばセコい技法て、すが , 大量の比較 a21 に対して同じハッシュ値を生成してしま 索が失敗したとき ( データが見つからなかっ を行うプログラム ( たとえば diff) ては実行の います。プログラムを書くにあたっては , たとき ) に場合分けされています。探索に成 実験を行って , 生成されるハッシュ値が均 向上にかなり寄与します。 功したときがハッシュ法の性能を表現する この方式は , データが等しいか等しくな 等に分散することを確かめる必要がありま と考えられます。 いかの比較しか扱えないのて , データの大 実際に値を代入して計算すると , 「再ハッ す。 小が問題になる場合には利用て、きません。 シュ時に順番にバケットを調べる」という単 ハッシュ関数は , て、きるかぎりキーのす べてのビットがハッシュ値に影響を与える 純な方法ては , 表の使用率が 80 % のとき 3.0 9 , 4 , 7 , 0 , 5 , 2 , 1 , 6 , 8 ・・・・・・ ( a ) 86 CMAGAZINE 19 11
ROM 化 考察 プログラミング ロケータを用いた ROM 化 Secti0112 野口修男 を使ったボ、一ドが多い。 V25 には特殊機能レ どこまて、の対応がて、きているかは製品によ DOS コンヾイラの ジスタがあり , 周辺チップがメモリに割り って大きな違いがある。ロケータの購入前 付けられている点が特殊だ。ノヾンクレジス に確認を勧める。 タはマルチタスクのスイッチングに高速て、 , かっ便利だ Microsoft C( 以下 MS-C) や Turb0 C の V40 チップには使い慣れた周辺チップをつ プログラムを ROM 化するにはどうすればよ けているのが特長だ。 いのかという答えを出す前に , まず実際に 今回は , この中から V25 のコードを選択し MS-C と Turbo C て、生成可能なコードは ROM 化を試みた結果 , どのような問題が発 た。これにはふたつの理由がある。ひとつ 生するかを考えるのが妥当だろう。 80X86 用のコードだけだ。したがって , この は各種のポードが入手可能て、あること。も コードを使用する CPU チップも 80X86 互換チ 多くの ROM バーナー ( プログラマ ) は HEX うひとつはシリアルポートが 2 本内蔵されて ップとなる。 lntel だけをとっても 8088 , ファイルを入力フォーマットとしている。 おり , このうちの 1 本をコンソールに したがって , HEX ファイルを出力するのが 8086 , 80186 , 80286 , 80386 , 80486 があり , 1 本を Turbo Debugger を使ったリモートデ NEC の V シリーズを加えれば , チップの選 必要最少条件て、ある。 ROM 化専用のコンパ バッグ用に割り付けるためて、ある。 択肢は大きい。ただ , 通常の制御機器を作 イラ以外 , EXE ファイルしか出力て、きな 成する場合には , たんに CPU チップだけて、 い。したがって , EXE ファイルを HEX ファ ーットフォーム はなく , シリアル , タイマ , インタラブト イルに変換 , あるいは OBJ ファイルをリン などの周辺チップを含んだ CPU チップを選 クして HEX ファイルを出力するソフトが必 択するケースが多い。これは , とくに量産 要て、ある。 開発に必要なハード / ソフトを予算にあわ の場合に価格への影響が出るからだ。 一般にこのようなソフトをロケータと呼 こて、は私の せて組まなくてはならない この場合 , lntel には 80186 しかない。とな んて、いる。ロケータは入力ファイルの相対 個人的な好みも含めて選択理由を述べよう れば NEC の V シリーズがクローズアップさ アドレスからターゲットボードの絶対アド (TabIe 1 参照 ) 。 レスへの変換を行うのて、この名前がある。 れる。 市販の V シリーズチップて、は , V25 や V40 C て、はて、きない , プログラム中にアドレス指 パソコン 定することが , ロケータの主要な仕事だ TabIe 1 ROM 化のための八一ド / ソフト ROM 化て、きることとそのコードが正常に 開発システム選択の中核はパソコンだろ 動作することとは別だ。通常 , ロケータに う。日本て、は , ほとんどのソフト会社が PC は置き換え用のスタートアップコードが付 ー 9801 を選択している。そのほかのソフトの 属している。 Turbo C, MS-C に付属してい 開発やワープロて使用することを考えると るスタートアップコードは , DOS のメモリ 当然の結果かもしれない。しかし , IBM 互 構成と PC ー 9801 や IBM 互換機のハード構成 換機のスピードは ROM 化する際には一考に を意識して書いてあるのて、 , このコードを 値する。現在 , 筆者は Turbo C 十十を CP386 ROM 化しても正しく動作しない。ロケータ の 33MHz マシンて使っているが , だいたい に添付されているスタートアップコードは のモシュールのコンパイルは一瞬て終了す この点を改善しかっランライムライプラリ る。しかも , リモートデバッガのシリアル の動作に必要な処理も施してある。ただし 特集 ROM 化プログラミング考察 63 P ノ 7 の選択 ノヾソコン旧 M 互換機 V25 ホード Microsoft C/Turbo C Paradigm LOCATE ROM ライタ ℃ E リモートテノヾッガ