, 新 MS ー DOS プログラミンク入門 ログーマのための TabIe 4 拡張メモリの内容 TabIe 3 オフセット 十 0 十 4 十 6 十 8 十 A 十 C 十 D 十 E 十 1 0 十 60 十 64 十 68 十 6A 十 130 十 132 ーン 常駐情報 ( 保存する情報 ) バイト数 4 2 2 2 2 1 1 2 4 4 x 8 2 4 4 2 X33 2 2X255 2 4 項目 常駐チェック Ma ic NO. ('CDEV') 常駐情報 ( メインメモリ ) のノヾラグラフ数 EMM 八ンドル ( EMS 未使用のとき一 1 ) マスタ 8259A 割り込みマスクポートアドレス スレープ 8259A 割り込みマスクポートアドレス マスタ 8259A 割り込みマスク スレープ 8259A 割り込みマスク 保存した内部 FCB プロック数 内部 FCB プロックのアドレス 内部 FCB プロック情報内部 FCB プロックのテパイスへッダの旧アドレス 内部 FCB プロックのテパイスへッダの旧オフセット CLOCK テパイスを指す旧ポインタ CON テノヾイスを指す旧ポインタ 保存した割り込みべクタ数 割り込みべクタ番号 割り込みべクタセープ領域 十 A 十 2E 十 30 4 2 2 2 2 2 330h 拡張メモリ情報 十 3CCO 330h 十 360 330h 識別コード ( ℃ DEV') 次格納番号 ( 0 ~ 19 ) 項目 常駐情報 1 常駐情報 0 (Table 3 ) 常駐情報格納領域オフセットアドレス 19 常駐情報 19 常駐情報格納領域オフセットアドレス 1 常駐情報格納領域オフセットアドレス 0 常駐情報格納個数 ( = 20 ) 設定状態の復元 べクタを元に戻す ⑥解放するデバイスドライバをチェ そのほか ⑦常駐部を解放する から外す 90 C MAGAZINE 1992 2 01 シリーズて、サウンドボードなどの制限が モリは 1 ページしか使用しないため , PC-98 をセットしておくことにしました。拡張メ ラフ常駐させる情報の中に EMM ハンドル値 EMS のバージョンを 3.2 以降とし , 1 パラグ 常駐量はほとんど変わりません。そのため , 収めることは難しいため , メインメモリの しかし , デバイスドライバを拡張メモリに て拡張メモリに格納することがて、きます。 名をつけることにより TabIe 3 の情報をすべ 4.0 以降にすれば EMM ハンドルにハンドル ものを常駐させます。 EMS のバージョンを きは ,TabIe 3 から拡張メモリ情報を除いた 格納している ) 。 EMS メモリを使用しないと す ( 実際は Table 3 のすべてを拡張メモリに に常駐させ , 残りは拡張メモリに格納しま 1 パラグラフ ( 16 バイト ) だけ , メインメモリ S メモリを使用するときは TabIe 3 の最初の 内容を Table 3 , TabIe 4 に示します。 EM 略て、す。保存する常駐情報と拡張メモリの 以上が登録時と解放時における動作の概 割り込みべクタ内容 保存した EMM 八ンドル数 EMM 八ンドル あるため , ページフレームを 4 ページ取れな い場合て、も動作するはずて、す。 レバ、メモリⅣ 0 バンク方式 ) の復元 とを行う必要があります。 完璧を期すためにはさらに次のような 完璧な動作を目指して ラ に支障はないと思います。 のはほとんどないと思われますから , とく バイスて、はプロテクトメモリを使用するも ため , 対応を省略しました。キャラクタデ リティて、プロテクトメモリを管理している 0386 マシンて、は仮想 8086 モードのユーティ 筆者は 80286 マシンを所有しておらず , 8 ロテクトメモリの復元 望があれば対処してみたいと思います。 法は今回の手法の延長線上にあります。要 日本語 FEP をバンクメモリに格納する方 ずて、す。 などにバンクメモリの復元が必要となるは 日本語 FEP をバンクメモリに格納するとき メモリが使用されているものと思われます。 られましたが , 古い機種て、は今て、もバンク 現在て、は EMS ポードに完全に取って変わ 各種ハードウェア ( LSI など ) の設定状態の 復元に関しては , デバイスドライバがグラ フィックを使用する場合などに必要となり ます。 LSI の状態をそのままにしておくとグ ラフィック VRAM の内容が表示されたまま になったりします。割り込みコントローラ 8259A はこれの代表例て、す。 ステム固有のバッフアの内容 システム固有のバッファ ( または ROM-B IOS, MS-DOS て、使用されていないバッフ ァ ) の内容を変えられた場合 , そのバッファ のアドレスがわからないと対処のしようが ありません。 ADDDRV/DELDRV コマンド て、もシステム固有のバッフアを操作して常 駐部のアドレスを取得しています。 まとめ これらを対処すれば ADDDRV/DELDRV コマンドを完全に超えることがて、きますが , 機種ごとに対処法が異なるため , それほど 簡単て、はないてしよう。次回は筆者自作のキ ャラクタデバイス登録ユーティリティ Ccha rdev ] の使用法や制限を中心に解説します。 ツ
TabIe 1 p 「 intf の変換文字 変換文字 d, i 符号つき 10 進整数として出力する long の符号つき 1 0 進整数として出力する 8 進整数として出力する ポインタを 16 進整数として出力する 符号なし 10 進整数として出力する 16 進整数として出力する ( 0 ~ f ) 1 6 進整数として出力する ( 0 ~ F ) 浮動小数点数を 1 23e 十 45 または 123E 十 45 のような仮数指数形式で出力する 浮動小数点数を 123.45 のような絶対形式で出力する g, G 数値に応じて , ・ g ' なら・ e ' または・ f' , ・ G ' なら・ E ' または・ f' て出力する 何も出力はせす , その時点まてに出力した文字数を , 引数として与えた int へのポインタの 指す先に格納する 文字として出力する 文字列を出力する ( 引数が NULL なら " ( n ⅶ ) " ) setvbuf. c int setvbuf(FlLE *fp, char *buf, int type, int size) fp の指すストリームのバッフアを標準のバ ッフアから buf の指す領域に切り換えます。 バッフアのサイズを size て、指定します。 type には , stdio. h て、定義されている以下 のマクロを使って , どのようなバッファリ ングを行うかを指定します。 IOFBF 通常の / ヾッファリング IOLBF 行単位のノヾッファリング IONBF バッファリングをしない ( 成功したら 0 , 失敗したら一 1 を返しま 意 味 D 0 P X f printf. c int printf (const char * fmt, ... ) ・ フォーマット fmt て、指定されたとおりに fmt の次以降の引数を標準出力ストリ ームに 出力します。 成功したら出力した文字数 , 出力に失敗 したら EOF を返します。 フォーマットには , 各引数それぞれにつ いて次の要素を並べて指定します。 ・フラグ ・フィールドの最り、幅 精度 ・変換文字 ・ % ' および変換文字以外の要素は省略てき ます。 変換文字とは , 引数をどのような型とし て扱うか , また , どのような形式に変換す るのかを決めるものて、 , Table 1 にあげた文 字のいずれかを指定します。 フラグには Table 2 の文字のうちいくつか を指定します。 fprintf. c int fprintf(file * fp, const char *fmt, ... ) ・ 標準出力ストリームて、はなく fp の指すスト 82 C MAGAZINE 1 2 2 TabIe 2 printf のフラグ フラグ 意味 数値の前につける符号は , 正のとき・ ' ( 空白 ) , 負のとき・一 ・十 ' フラグと同時に指定されると無効 浮動小数点数なら , 常に小数点を出力する また , 変換文字が・ g' , ・ G' なら , 小数点以下の 0 も出力する 1 6 進整数なら , 先頭に Ox または OX を出力する 8 進整数なら , 先頭に常に 0 を出力する フィールド幅を p 「 intf の引数から読み込む 引数に負の値を与えると , ' フラグをも指定したことになり その絶対値がフィールド幅になる 左詰めで出力する 数値の前につける符号は , 正のとき・十 ' , 負のとき・ 右詰め出力のとき , 左の空き位置を 0 で埋める ( 空白 ) 一十 0 sho として出力する long として出力する long doub 厄として出力する L
アルゴリズム・テータ構造入門 行います。これが分布数え上げソートの原 理て、す。 実例をあげて説明しましよう。キーの範 囲は 0 以上 10 以下だとします。また , データ の並び 7 , 1 , 4 , 2 , 7 , 8 , 2 を整列するもの としましよう。各キーの出現する回数とそ の累計を Table 1 に示します。出現回数の累 計から , そのキーを持つデータが整列後に 配列のどの位置に置かれるかがわかります。 キー k を持っ要素の個数を a , 0 以上 k 以下 のキーを持っ要素の個数 ( TabIe 1 の累計 ) を b とすると , キー k を持っ要素は , 配列の ( b ー a) 番目から ()— 1 ) 番目に位置することにな ります。 たとえば , キー 1 の場合 ,Table 1 から a = 1 , b = 1 なのて、 , 配列の 0 番目 ( つまり先頭 ) に置かれることになります。また , キー 2 は a = 2 , b = 3 なのて、 , 配列の 1 番目と 2 番目に 置かれることになります。同様にしてキー 4 は 3 番目 , キー 7 は 4 番目と 5 番目 , キー 8 は 6 番目に置かれます。この情報を元に , 配列 の要素を移動すれば , 分布数え上げソート は完了て、す。 分布数え上げソートという名称は , キー の分布を数え上げてその情報をもとに整列 TabIe 1 キーの分布 分布数え上けソート (distribute counting so 1 : / * 整列の対象となるデータの型。 * / 2 : typedef struct { 3 : int key; / * 整列のキー。 0 から M の範囲内でなければならない。 4 : int other; / * その他の情報。 5 : } DATA; 6 : 7 : / * キーは 0 から M までの範囲の整数。 8 : #define 100 9 : 10 : / * キーの分布を数え上げるための配列。 int countCM + 1]; 12 : 13 : / * 大きさ n の配列 a を分布数え上げソートによって整列する。 14 : 結果は配列 b に得られる。 15 : void dist count_sort(DATA a[], DATA bC], int n) 16 : { 17 : int i; 18 : / * カウンタをすべて 0 にする。 19 : 20 : for (i 0 ; i く = M; i + + ) count[i] 22 : / * キーを数え上げる。 23 : for (i 24 : 0 ; i く n; i + + ) count[a[i]. key] + + ; 25 : 26 : / * 数え上げたキーの累積度数分布を求める。 27 : for (i = 0 ; i く M; i + + ) 28 : countCi + 1] + = count[i]; 29 : 30 : / * 度数分布にしたがってデータを配列 a から配列 b にコピーする。 31 : for ( i = n ー 1 ; i 〉 = 0 ・ i--) 32 : bC--countCaCi]. keyj] = a[i]; 33 : 34 : } List 2 を行う ことからきています。 ときとまったく同じて、す。また , 8 行目て、 次に , プログラム (List 2 ) を見てみましょ は , キーの最大値を表す定数 M をマクロ定 う。関数 dist count sort が分布数え上げソ 義しています。 11 行目て、定義されている配 ートを行うルーチンて、す。この関数は , 配 列 count は , キーの個数を数え上げるための 列 a の内容を昇順に整列して , その結果を配 ものて、す。 列 b に返します。パラメータ n は , 配列 a に含 15 ~ 34 行目が関数 dist count sort の本体 まれる要素の個数て、す。 て、す。まず始めに , 20 ~ 21 行目の for 文て、配 これまて、に紹介した整列ルーチンとは違 列 count のすべての要素を 0 にします。 24 ~ 2 って , 与えられた配列そのものを整列する 5 行目て、キーの個数を数え上げて , 28 ~ 29 行 のて、はなく , 整列された配列のコピーを作 目の for 文て、累計を求めています。この段階 成することに注意しましよう。今まて、に紹 て、 , 配列 count には TabIe 1 の累計の部分の 介したアルゴリズムて、は , 要素を比較交換 値が入っていることになります。 することによって , 最終的な状態に向かっ 最後に , 32 ~ 33 行目のループて , 配列 co て遷移していきました。これに対して , 分 unt の内容をもとに , 配列 a の各要素を配列 布数え上げソートて、は , キーの分布を基に b のあるべき位置にコピーします。このルー して , 要素をいっきょに最終的な位置に移 プから抜けた時点て、 , 配列 a の要素を昇順に 動するのて、 , 配列のコピーを作らずに済ま 整列したものが配列 b に得られます。 すことはて、きません。 ところて、 , この for 文て、は配列 a の末尾の要 2 ~ 5 行目て、整列の対象となるデータの型 素から先頭に向かって処理しています。な を定義していますが , これはビンソートの ぜ後ろから前へと処理するのかというと , 累計 個数 0 0 0 1 つっ ) 4 5 6 7 8 9 0 1 3 3 4 4 4 6 7 7 7 一 1 っム 0 1 0 0 2 1 0 0 対象となるデータの並びは 7 , 1 , 4 , 2 , 7 , 8 , 2 アルゴリズムとデータ構造入門 73
/ * 引数が即値の場合の %con port Table 4 cc から起動されるツール 関数本体の定義 * / 内容 ツール プリプロセッサおよびコンノヾイラ /usr/ccs/lib/acomp オプティマイザ /us 「 /ccs/lib/optim のように , asm 関数として定義します。 基本プロックアナライサ ( ー p などで使われる ) この /usr/ccs/lib/basicblk とき , 引数のストレージモード , つまり reg アセンプラ /us 「 /ccs/bin/as ister か , メモリ上か , それとも即値かなど /usr/ccs/bin/ld リンクエテイタ の条件によって , 実行する命令を指定する TabIe 5 べンチマークテスト結果 ことがて、きます。たとえば , outb 命令の場 「 egister 合には , 一度 AX / EAX へ出力すべき値を口 Machine/compiIer int ードしてこなければなりません。レジスタ UNIX-svr4/386 ( ー 0 ) 0. 10 同士の場合ならば , UNIX-svr4/386()o -0 ) 0. 1 2 movl val, %eax TabIe 6 他マシンでの測定結果 のように , 無条件に 32 ビットコピーしても かまいませんが ( メモリの節約になります ) , 「 egiste 「 auto auto lnt a utO Machine/compiler int short ng multiply dbl オペランドがメモリ上にあった場合には , movb val, % 引 C 「 ay X-MP()o vecto 「 s) 0.0567 0.0656 0.0822 0.366 0.821 0.082 Sun 3 / 75M ( 4.2 , -0 ) 0.50 0.81 0.83 2.85 20. 7 のようにきちんとバイトコピーを行わない UN Ⅸー sv 「 4 / 486 ( ー 0 ) 0. 10 0. 1 8 0. 1 0 0.33 0.63 と , 場合によってはメモリ参照例外が起き ることがあるのて、注意が必要て、す。 %reg port ; mem val ; スクに収録されていたべンチマークテスト このストレージモードには , のように ; ( セミコロン ) て、区切って記述て、 を実行してみました。そのサマリを Table 5 コンノヾイラがイ吏用しているテン きます。 に示します。 treg また , asm 関数のネストした呼び出しはて、き ボラリレジスタ オプティマイズのあるなしてあまり極端 ませんのて、 , 呼び出し時に注意が必要て、す。 な差は見られませんが , register int, auto コンパイラが割り当てた regis もうひとつ , SVR4 / 386 のアセンプラは , long, func call て、一 0 オプションっきのほう ter 変数 が優秀な成績を示しています。 treg または ureg インテル系 CPU て、ありながら , オペランド reg 即値 の順序は , registerint について -S て、出力したアセン con プラリストを比較してみると , 明らかにム メモリ opecode source, destination mem ダなレジスタのロードが削除されているよ 1 ab という , VAX や 68000 風の形式を採用してい ラ / ヾノレ 引数のストレージモードが定義 ます。生粋の MS ー DOS 出身のプログラマは うて、す。たとえば , error きっとしばらくまごっくて、しようから , ち ① a = a 十 b 十 c ; されていない場合工ラーを起 よっと頭の片隅て、意識しておく必要がある ② b = a > > 1 ; こさせる て、しよう。なお , 即値は $ を , レジスタは % の 6 個 ( error を入れると 7 個 ) が用意されてい ③ a = b % 10 ; ます。ストレージ条件指定は , をプレフィックスとしてつけます。 の一連のコードて、は , ①式て、変数 a に値が代 ストレージモードバラメータ 入されていますが , その値は②式てるの代入 コード生成 のようにして行います。ひとつの条件は , 計算にそのまま使われた後 , ③式て、 a に違う 次の条件が出てくるまて、有効て、す。たとえ 値が代入されているのて、 , ①式において変 ば , 引数 val が reg の記述は , 今回はコード生成 , オプティマイズとい 数 a への代入は必ずしも必要て、ないことがわ かります。この部分のアセンプラ出力を比 %reg val った項目についても見てみます。一応 , cc movl val, %eax には -O というオプティマイズ用オプション 較したのが Fig. 6 て、す。 が用意されてはいますが , いったい , Fig. 6 に見られる最適化などほんの些細 どの な差と 0 、えるかもしれませんカ : , この一連 程度オプティマイズされるのて、しようか ? となります。 複数の条件を指定する場合は , まずは , C マガジン ' 90 年 10 月号の付録ディ の式はループのもっとも深い部分て、出てく func call i nt multiply autO long 0. 1 0 0. 1 2 auto short 0. 1 8 0. 1 8 a utO dbl 0.63 0.58 0.33 0.66 fu nc call ureg 96 C MAGAZINE 1992 2
ワンポイント プログラミング 講座 マウスの左ボタンがクリックされると , そのときの行番号を負の値として返すのは 前述したとおりて、すが , ェラーレベルて、は TabIe 3 のように対応します。また , 数字キ ーが入力されるとその数字を返します (Tab le 4 ) 。右ボタンが押された場合 , または回 あるいはキーが押された場合は , 0 を返 します。 バッチファイルのサンプルを付録ディス クに収録してあります。参考にしてくださ キーボードからの数字入力の監視 while (m—hit = の { / * m-hit = 0 : 無押下 * / m-hit = m-read(&jerry); / * 1 : 左 2 : 右 3 : 両方 * / List 1 1- り 0 れ 0 マウス情報設定の構造体 / * マウス情報設定用構造体 * / struct Mouse { / * 右ボタン , 左ボタンの状態 * / int rb, lb, / * y , x 座標 YP, XP, / * 行列 ( 文字座標系 ) ro 響 , CO 1 ; List 2 1- りなっ 0 -4 ′ 0 Table 4 数字キーを押したときに返されるエラーレベル値 数字戻り値 工ラーレベル 1 TabIe 3 マウスクリック時に返されるエラーレベル値 行番号 戻り値 工ラーレベル 255 ファンクション 03H てマウスカーソルの位 置やボタンの状態が取得てきるのにもかか わらず , ファンクション 05H から 08H に似た ようなファンクションがたくさんあります。 これらは , 前回同じファンクションが呼ば れてから今回呼ばれるまての間のボタンの 押下状況を取得してくれます。すなわち , ファンクション 03H て、は , 今現在のボタンの 状況しかわかりませんから m read() の間隔 が長いとボタンを押しても検出てきない場 合が出てきますが , ファンクション 05H から 08H て、は前回の呼び出しから何回押されて最 後に押された位置はどこてあるかを返して くれるのてす。ただし , これらのファンク ションは , ボタンごとの押下時 , 解放時て 分かれていますのて , 両方のボタンの状態 を一度に知ることはて、きません。 今回のプログラムて、は , ループ内の処理 はマウス状態の取得だけてボタン押下の取 りこばしの心配はなかったため , ファンク ション 03H を使用しました。 なお , マウスカーソルの形状の設定を Ta もしろくはありません。 バッチファイルから起動された場合は , ble 5 に示します。 マウスのボタンが押されたときの行番号ま 参考文献 たは数字キー入力をエラーレベルとして返 「 C 言語の応用 50 例』 ( ソフトバンク ) すのて , 工ラーレベルをチェックすること 今回のプログラムは基本的にバッチファ TMS-DOS プログラマーズリファレンスマ ていろいろな処理へ分岐するためのツール イルから起動します。コマンドラインから ニュアル」 (NEC) 起動しても , マウスが表示されるだけてお として利用することがてきます。 ワンポイントプログラミング講座 147 参考までに 1 1 ' 9 ' ー 25 25 9 231 9 0 っ 4 ト イ 3 タ 4 定 設 6 び 図 定 設 2 状イ 3 5 カ ス ウ マ 0 1 2 3 4 5 6 1 2 3 4 5 6 7 8 9 設定値 上位 , 下位 0X00 0X80 , 0X00 OxCO, OxEO, 0X00 Ox FO, OxOO OxF8, OxOO OxFC, 0X00 OxFE, 0X00 OxFF, 0X00 OxFF, 0X80 OxCO OxF F, Ox EC, 0X00 OxC C, 0X00 0X86 , OxOO 0X06 , 0X00 0X03 , OxOO OxO 3 , 0X00
ックして , そこにロードしていきます。 EXE 型のデバイスドライバの登録 十 0 MS-DOS 3. x 以降て、は EXE 型のデバイス ドライバを登録て、きます。そのため , ロー 十 3 ~ 十 4 ドしたデバイスドライバの先頭の 2 バイトが 十 5 ~ 十 1 2 5Ah, 4Dh または 4Dh, 5Ah の場合は EXE 型 十 1 3 のデバイスドライバとみなしてセグメント 十 1 4 ~ 十 1 7 参照をリロケーションします (Table 1 ) 。 CON 日 G. SYS の DE Ⅵ CE = の後の文字を指す 十 18 ~ 十 21 ポインタ 初期設定ルーチンの呼び出し ズを計算します。ひとつのファイルに複数 スクに収録しました ) 。 リクエストヘッダを作成してデバイスド のデバイスドライバが含まれているときに Get Status は最大のサイズを常駐サイズとします。 ライバの初期設定ルーチンを呼び出します。 Get Page Frame Segment Address TabIe 2 のリクエストヘッダの中て次の項目 Get Unallocated Page Count 割り込みべクタの復元 をセットして , デバイスドライバのストラ AIIocate Pages テジェントリルーチンと割り込み工ントリ デバイスドライバが変更した割り込みべ Map/Unmap HandIe Page クタの元の値をセープします。 C コンパイラ ルーチンを続けて呼び出します。 DeaIIocate Pages ①コマンド長 = リクエストヘッダのバ のスタートアップルーチンが零除算割り込 Get Version イト数 みを変更しているため , 零除算割り込みを Get AII HandIe Pages ②コマンド番号 = 0 この中て、確保されている全ページ数の配 除外しています。零除算割り込みを書き換 ③ステータス = 0 えるデバイスドライバはまずないと思い簡 列を取得する CGet A11 Handle Pages] が ④ CONFIG. SYS の DEVICE= の後の文 単にするため手を抜きました。 ポイントとなります。デバイスドライバの 字を指すポインタ 初期設定ルーチンを呼び出す前後て、 , この EMM ハンドルのセープ EMM ファンクションを実行し , 増えた EM 常駐サイズの確認 デバイスドライバが使用した EMS メモリ M ハンドルがデバイスドライバが確保した ハンドルということになるため , セープし の EMM ハンドルをセープします。本ューテ デバイスドライバの返り値から常駐サイ ズを調べます。 Table 2 のリクエストヘッダ ィリティて使用している EMM ファンクショ ておきます。そして , デバイスドライバ解 のフリーメモリ開始アドレスから常駐サイ ンは次のとおりて、す ( 詳しい資科を付録ディ 放時に , この EMM ハンドルも解放します。 Fig. 8 内部 FCB プロックの解析情報 CES:BX 十 04h] オフセット 内 容 00h ~ 03h 次の内部 FCB プロックへのポインタ 04h ~ 05h 内部 FCB プロック数 (n) 06h—3Ah 内部 FCB プロック 0 3Bh—6Fh 内部 FCB プロック 1 70h—A4h Table 2 江コマンドのリクエストヘッダ 内容 オフセットアドレス コール時 レコード長 ( リクエストヘッダのバイト数 ) コマンド番号 リターン時 ステータス テパイスドライバ占有最終アドレス ( フリーメモリ開始アドレス ) オフセット 内容 0000h : 空き 00h ~ 01 h その他 : 使用中 ( 詳細不明 ) 不明 テノヾイスドライノヾを 07h—OAh テノヾイスへッダのアドレス 登録する際に差し替 OBh—OCh テパイスへッダのオフセットアドレス える必要あり 不明 20h—2Ah ファイル名十拡張子 ( 11 バイト ) 不明 35h * 1 内部 FCB プロック n—l 内部 FCB プロックのサイズは次のとおり 注 ) 1 . 35h : DOS 3. x , 3Bh : DOS 4. x 2. ES : BX は DOS ファンクション 52h で取得する 3. 00h ~ 03h の次の内部 FCB プロックへのポインタは下位ワードが FFFFh でチェーンの終了を意味する 88 C MAGAZINE 1 2 2
フトウェアは , pkgadd コマンドてインスト ール可能なものが添付されてきます。 このようにアドオンのインストール方法 が統一されていることて、 , シュリンクラッ プソフトマーケットの可能性が一段と広が ったといえるて、しよう。 サードバーテイソフトウェア 肝心のサードバーテイソフトウェアて、す が , そのディレクトリとして , 参考文献 [ 1 ] があります。この本は実に 400 ページ以上も のポリュームがあり , データベースから健 康管理支援にいたるまて、 , 幅広いソフトウェ アがすて、に流通していることがわかります。 バーティションとスライス 普通の UNIX システムて、はほかの OS と共 存することはありませんが , AT 互換機て、は MS-DOS との共存は必要条件て、す。このた め , HDD 上て、 MS-DOS と UNIX にパーティ ションを切って使いわけがて、きるようにな っています。 UNIX2€—ティションの中て、 , ファイルシ ステムを論理的に分離する単位がスライス て、す。スライスは , 普通の UNIX て、いうとこ ろのパーティションに相当します。 MS-DOS とのパーティションの切りわけ 方について若干注意すべき点がありますの て、 , 参考文献 [ 2 ] , [ 3 ] などを参照してく ださい。簡単にいえば , ・ MS-DOS'€—ティションを最初のパーテ TabIe 1 システムのステート一覧 Fig. 1 CC ・ i n itta b の一例 ・ sysinit : /sbin/chkconsole >/dev/sysmsg 2 > & 1 ・ sysinit : /sbin/autopush -f /etc/ap/chan. ap 旧 : 2 : initdefault . 「 0 : 0 : wait : /sbin/rcO 0 幵 1 > /dev/sysmsg 2 > & 1 </dev/console . 1 : wait : /sbin/rc 1 1 >/dev/sysmsg 2 > & 1 く /dev/console 「 2 : 23 : wait : /sbin/rc2 1 >/dev/sysmsg 2 > & 1 く /dev/console sc : 234 : respawn : /us 「 /lib/saf/sac -t 300 co : 12345 : respawn : /sbin/vtgetty console console イションにすること ・最後のシリンダは空けておくこと ということて、す。 プートシーケンス ば , システムのシャットダウンコマンドは , n, /usr/bin/telinit を使用します。たとえ ステートの切り替えには , /sbin/shutdow Table 1 にステートの一覧をあげておきます。 話がややこしくなっています。 テートというものがいくつかあって , 少々 bat にあたります ) , SVR4 にはシステムのス は簡単て、すが (MS-DOS て、いえば autoexec. cal によってシステムの初期化を行うのて、話 しれません。 BSD 系て、は /etc/rc, /etc/rc. 10 く違うのは , システムのプートの過程かも BSD 系の UNIX と SVR4 とて、もっとも大き # shutdown -y -i0 -gO て、す。 システムがプートされ , SVR4 のカーネル が起動すると , カーネルは内部の初期化を 行ってから init と呼ばれるプロセスを作りま す。 init は , すべてのプロセスを生成する母 親プロセスて、す。どのステートて、どういっ たプロセスを生成するかは , /etc/inittab とい うファイルに記述されています。 プート時のステート初期値も /etc/inittab に記述されています。非常に大事なファイ ルて、すから , 不用意に書き換えないよう , 十分注意してください 0Fig. 1 に inittab の一 例をあげておきます。この中の , initdefau lt という記述のある行の数字が , システムの 初期ステートて、す。 inittab ファイルて、は , それぞれのフィー ルドは : ( コロン ) て、区切られます。最初の 機能 機能番号 0 1 S 2 3 4 5 6 パワーダウンステート 管理用ステート シングルユーサステート 通常のマルチューサステート 機能 シャットダウン十リプート ROM ステート ( またはリプート ) ユーザ定義ステート ネットワーク ( ファイルシステム ) ステート TabIe 2 sysinit respavvn bootwa it bOOt ′ a it once initdefault コマンド in ab のコマンド システムの初期ステート指定 一度だけ実行される。 init はそのプロセスの終了を待たずに処理を続行 コマンドが終了するまで待つ システムがプートされたときにのみ実行される システムがプートされたときにのみ実行される ただしプロセスの終了を待つ プロセスが終了したら , 再度起動する システムのイニシャライズ コンソールのログインプロンプトが出る前に必ず実行される 92 C MAGAZINE 1992 2
djgcc 詳解講座・Ⅷ 0 刪 World じて、す。 int sscanf (char * str, const char *fmt ) ・ 標準出力ストリームて、はなく str の指す文 字列から読み込むこと以外 , scanf ( ) と同 じて、す。 アップデート情 今回はオリジナルの djgcc のバージョンア ップはありませんて、した。バーションは 1 . 05(patch5) のままて、す。 98 バッチのバージョンアップ その代わりというわけて、はありませんが , 98 パッチが , 前回の djgpp98g. レ h から djgpp 98h. レ h にバージョンアップされました ちらもオリジナルの patch5 に対応するもの て、すが , 変更点が異なっています。 TabIe 4 テスト結果 ( ドライストーン ) コンバイラ djgcc (optimized) djgcc (not optimized) towns gcc (exe386,optimized) towns gcc(exe386 not optimized) towns gcc ( 「 un386 optimized) towns gcc ( 「 un386 , not optimized) 80386 ( 16MHz ) IM ノヾイト , 80387 なし Table 5 テスト結果 ( ウェットストーン ) コンノヾイラ djgcc (optimized) djgcc(not optimized) towns gcc(exe386,optimized) towns gcc(exe386,not optimized) towns gcc(run386,optimized) towns gcc(run386,not optimized) 80386 ( 16MHz ) IM ノヾイト , 80387 なし Fig. 1 gcc(djgcc と towns gcc ) のオプティマイズオプション -fstrength-reduce -fomit-frame-pointer —fcaller—saves —fcombine¯regs —finline—functions —fforce—mem -fforce-addr djgpp98g. レ h と異なる点は , ・ g032 / debug32 終了時にか無効にな るのを修正 ・ debug32 に Towns GCC の simple a. out たバグを修正 相互のリダイレクト ) が無効化されてい ・ 1r2 , 2r1 ( 標準出力・標準ェラー出力の ンクションコールに対応 ・サポートされていなかった一部のファ ァンクションコールに追加 ・ g032 のバージョンを取得する機能をフ ドライストーン値 3704 3030 2000 1587 5263 3846 ウェットストーン値 2.13 K 2.17 K 19455K 93 80K 70.27K 70.08K ファイルサイズ ( ノヾイト ) 241 1 9 (). out) 24119 (). out) 29324 (. exp) 29780 (. exp) 29324 (. exp) 29780 (. exp) ファイルサイズ ( バイト ) 19483 (). out) 19483 (). out) 28468 (. exp) 28464 (. exp) 28468 (. exp) 28464 ( exp) ファイルの実行機能を追加 ・標準入力のリダイレクトのバグを修正 となっています。 10 月号特集の追試結果 すて、に 12 月号の djgcc 詳解講座のアップデ ート情報て、触れていますが , オリジナルの djgcc は , すて、にパッチ 5 まて、がリリースされ ています。このパッチて、の変更のひとつに 80837 工ミュレータ emu387 の改良がありま す。 10 月号特集の Part4 のテストて、は , この 工ミュレータを使った場合 ( つまり 80387 な し ) て、は , ウェットストーンべンチマークが うまく動かないと記述されていますが , の改良により , ウェットストーンは実行可 能になりました。 また , 同じく Part4 の townsgcc のテスト 結果について , 開発者の方々から , townsg cc て、は , -msoft-float のバグなどが取られて いて , ウェットストーンなどは間題なく動 いているという御指摘を受けました。 town sgcc の最新バージョン (gcc 1 . 40 相当 ) を使 って再度テストを試みたところ , うまく動 作しました。 Fig. 1 の最適化オプションを指定して試み た結果 , TabIe 4 の値が得られました。お詫 びして訂正いたします ( テスト環境は , 10 月 号特集 Part4 と同じ PC ー 9801RA5 十 IM バイ ト十 80387 なして、 , djgcc は DOS 工クステン ダ g032 を , towns gcc は DOS 工クステンダ exe386 1 . 0 および run386 を使いました ) 。 この連載のページにかぎって , GNU General Public Licen に基づいた再配布を認めます。 ※ d ] gcc の数学関数は非常に遅いので , ソースの ERA 引 ONS を 1000 から 1 にしてコン八イルした 84 C MAGAZINE 1 2 2
を設定後 int86 ( 0X33 , ®s, ®s) ・ または , int86x ( 0X33 , ®s, ®s, &segs) ・ のように呼び出します。 今回はこの中から 7 個 ( ◎印がついたもの ) だけを使用しました。使用したファンクシ ョンについては , 呼び出し時のパラメータ 設定および戻り値について , Table 2 に詳細 を載せたのて , プログラムと見比べてくだ さい。そのほかのファンクションについて は , 誌面の関係上省略したのて参考文献を 参照してください TabIe 1 マウスドライバのファンクション一覧 機能コード 00H ◎ 環境のチェック 01 H ◎ カーソル表示 カーソル消去 02H ◎ 03H0 カーソル位置の取得 カーソル位置の設定 04H ◎ 左ボタンの押下情報の取得 、 05H 左ボタンの解放情報の取得 06H 右ボタンの押下情報の取得 ~ 07H 右ボタンの解放情報の取得 08 H カーソルの形の設定 09H ◎ マウスの移動距離の取得 OBH ユーサ定義サプルーチンのコール条件の設定 OCH ミッキー / ドット比の設定 OFH 水平方向のカーソル移動範囲の設定 10H 垂直方向のカーソル移動範囲の設定 カーソルの表示画面の設定 12H ◎ グラフィック用 VRAM の 4 面目の設定 13H ( ◎印は今回使用したファンクションです ) TabIe 2 使用したマウスファンクションの設定方法 まずは付録ディスクに収録した MOUSE. 00H : 環境のチェック ファンクション C をご覧ください マウスを使用できる環境かどうかをチェックします 機能 設定 AX = 0X00 今回のプログラムはマウスを表示後 , 左 戻り値 AX : 状態 0 : 使用可 右ボタンがクリックされるのをただ監視す ー 1 : 使用不可 ファンクション 01H : カーソル表示 るだけのものて、す。キーポードからの数字 マウスカーソルを画面上に表示します キーの入力も許すようにしたため , while ル 設定 AX = 0X01 戻り値 なし ープの中て、キー入力検知関数 kbhit ( ) を使用 02H : カーソル消去 ファンクション していますが , これがなければ List 1 のよう マウスカーソルを画面上から消去します 設定 AX = 0X02 戻り値 なし に , マウスのボタンが押されるまてマウス 03 H : カーソル位置の取得 ファンクション の現在の状態を取得する関数を繰り返し呼 現在のマウスカーソルの位置とボタンの押下状態を取得します 設定 AX=Ox03 んているだけてす。 戻り値 AX : 左ボタンの状態 0 : 離されている ボタンがクリックされると , ループから ー 1 : 押されている BX : 右ボタンの状態 0 : 離されている 抜けたときのマウスカーソルの位置の行番 ー 1 : 押されている CX : マウスカーソルの位置の水平座標 号を負の数字として戻り値に設定し , exit し DX : マウスカーソルの位置の垂直座標 ファンクション 04 H : カーソル位置の設定 ています。数字キーが押された場合 , その マウスカーソルの表示位置を設定します 機能 数字を戻り値に設定しています。 設定 AX = 0X04 CX = カーソルの水平位置座標 DX = カーソルの垂直位置座標 今回のプログラムは簡単なのて , あまり 戻り値 なし 説明はいらないと思います。リストを読む 09H : カーソルの形の設定 ファンクション マウスカーソルの形状と中心点を設定します 機能 ときの注意としては , 今回マウスの位置や 設定 AX = 0X09 BX = カーソルの中心点の水平座標 ボタンの状態などの情報を設定しておくた CX = カーソルの中心点の垂直座標 ES : DX = カーソル形状テータのアドレス 戻り値 なし めの変数をまとめてマウス情報設定用構造 ファンクション 12H : カーソルの表示画面の設定 体を定義したのて , マウスの情報の取得は 機能 カーソルの表示画面を設定します 設定 AX=Ox12 これを使用している点てす。関数 m read() BX = 表示当面 0 : レーシ 0 へ表示青 て、は , この構造体へのポインタをパラメー 1 : プレーン 1 へ表示赤 2 : プレーン 2 へ表示緑 3 : プレーン 3 へ表示灰色 ) タとしているのて記述に注意してください なし プレーン 3 への表示は , ファンクション 13H のグラフィック VRAM 使用の設定を行わな (List 2 参照 ) 。 いと使用でキません 146 C MAGAZINE 1992 12 ファンクション名 プログラムについて 戻り値
リームに出力すること以外 , printf ( ) と同 int sprintf (char * str, ・フォーマット指定子 フォーマットの中には , の数 , 失敗したら一 1 を返します。 読み込みに成功したら読み込んだデータ インタが指す先に書き込みます。 タを , 引数として指定されたいくっかのポ 込み , フォーマット指定子に対応するデー に , 標準入力ストリームから文字列を読み フォーマット (fmt) て、指定されたとおり int scanf(const char *fmt, ... ) ・ scanf. C 指定すること以外 , sprintf( ) と同じて、す。 出力するデータのリストへのポインタを const char *fmt ) ・ int vsprintf (char * str, vsprintf. c 指定すること以外 , fprintf( ) と同じて、す。 出力するデータのリストへのポインタを const char *fmt ) ・ int vfprintf(file * fp, vfprintf. c 使います。例を List 1 に示します。 て受け取ったデータなどを出力するときに 実際には , ほかの関数から可変引数とし します。 力するデータのリストへのポインタを指定 を直接引数として指定するのて、はなく , 出 printf( ) と同様て、すが , 出力するデータ int vprintf(const char *fmt, ... ) ・ vprintf. c て、す。 字列に書き込むこと以外 , printf( ) と同じ 標準出力ストリームて、はなく str の指す文 const char *fmt, ... ) ・ djgcci* 解講座・Ⅷ 0 刪 World じて、す。 sprintf. c 12 : } ・非空白文字 ・空白文字 ( ・ が指定て、きます。 に書き込みます。フォーマット指定子には , そして引数として指定されたポインタの先 容に従って標準入力からデータを読み込み , フォーマット指定子が現れると , その内 した空白文字をすべて読み飛ばします。 空白文字が現れると , 標準入力から連続 ・ % % ' とします。 非空白文字として・ % ' を指定したい場合は , の文字と同じ文字を 1 文字読み飛ばします。 非空白文字が現れると , 標準入力からそ 次の要素を並べて指定します。 vp 「 in 廿の使用例 ・ * ' にのデータを書き込まない ) LlSt 9 : main() vprintf(format, args) ; va start(args, format) ; va list args; 3 : vp(char *formag, ... ) 2 : #include く stdarg. h> 1 : #include く stdio. h> ・フィールドの最大幅 リームから読み込むこと以外 , scanf ( ) と同 標準入力ストリームて、はなく fp の指すスト const char *fmt, ... ) ・ int fscanf(FILE *fp, て入力されます。 に大文字を指定すると , データが long とし なお , 変換文字として , 小文字の代わり ずれかを指定します。 変換文字には , Table 3 にあげた文字のい ます。 ・ % ' および変換文字以外の要素は省略て、き ・変換文字 ・ h' (short として入力 ) ・ド (long として入力 ) ・フラグ 5 : 6 : 7 : 11 : TabIe 3 vp("vprintf: %d, % f \ n " , 123 , 65.4 ) ; scanf の変換文字 変換文字 0 e, f, E, F [ 探索集合 ] 意味 djgcc 詳解講座・ HellO GCC World 83 探索集合の先頭が・ % の場合 , 逆に含まれない文字だけを入力する 文字列のうち , 探索集合に含まれる文字だけを入力する 文字列として入力する 文字として入力する 浮動小数点数として入力する 1 6 進整数として入力する 8 進整数として入力する 1 0 進整数として入力する