DATA - みる会図書館


検索対象: 月刊 C MAGAZINE 1990年11月号
37件見つかりました。

1. 月刊 C MAGAZINE 1990年11月号

ROM 化 考察 プログラミング 用して MS ー DOS 上で動作する製品として ① ROM 化では ROM 部分と RAM 部分を分け などがあります。 組み上げた場合 る必要がある このシステムて、は ROM ー DISK がディスク それぞれのプログラムにはどのような違 ② ROM に置いた部分は書き換えができない 装置として動作しますからプログラムは RAM いがあるのて、しようか。同じ製品て、すから ③ DOS コールを使用しているライプラリは 上にロードして実行するためプログラミン 同じプログラムになってもよさそうなもの 使用できない グは DOS 上のものと変わりません。 て、す。 ROWI 部分と MS-DOS を ROM 化する DOS 上のプログラムと ROM 化プログラム RAM 部分を分ける との相違点は主として次の 3 点から生じま 最近は DR-DOS ( デジタルリサーチ ) , ROM す。 -DOS ( マイクロソフト ) などの ROM 化て、き る DOS が出てきました。 また , OS / 9 のように最初から ROM 化に対 応している DOS もあります。これらは ROM -DISK からプログラムをロードする部分も あるようて、すが , パソコンの ROMBIOS の ように DOS の一部は ROM 上て、そのまま動作 します。 このシステムはワープロ , ノートノヾソコ ン , FA 関連の組み込み機器 , などて、今後大 きく需要が伸びる可能性のあるものて、すが , 筆者はこれらに関してあまりくわしくない ため説明は省略させていただきます。 DOS と切り離して プログラムだけを ROM 化する 一般的に ROM 化といえばこのことて、 ,DOS は開発環境として利用するだけ。ターゲッ トのシステムて、は最終的な実行ファイルを S レコードや HEX フォーマットに変換して ROM 化を行った状態になります。本章て、対 象とするのもこのシステムて、す。上記の 2 種 類のシステムは別の機会にて、も取り上げて みたいと思います。 ー腴的な C 言語による ROM 化の手法 DOS 上のプログラムと ROM 化プログラム とて、はいったい何が違うのて、しようか。た とえば同じ製品を ① VME / ヾスのポードで ROM 化した場合 ②ディスク装置をもつ FA 用の / ヾソコンを使 ROM 化できないプログラム例 1 旧 int data = 2 : 3 : void func() 5 : / * 初期値を持っただータの書き換え data ニ 20 : ROM 化できるプログラム例 1 1 void func() 3 int data 4 : data = 20 : 5 : / * スタック上の auto 変数の書き換え ROM 化できないプログラム例 2 lSt 0 static int data data ニ 20 : / * 初期値を持ったテ・一タの書き換え 初期化関数 datan; int datal, data2, 2 : 3 : vo i d i n i t ( ) datal 5 : data2 ニ 6 : 7 : 8 : datan 0 0 1 よワ 3 / / 1 よ 特集 ROM 化プログラミング考察 37

2. 月刊 C MAGAZINE 1990年11月号

ROM 化 プログラミング 考察 この方法は初期値をもっ変数が少ない場 値が必要な変数に初期値を設定します 0List て、きません。 4 て、は変数は初期値をもたない変数となりま合に有効て、 , コンパイラの生成するメモリ それて、は応用問題て、す。 List 2 のプログラ すから RAM 上に領域がとられるため書き換配置にそれほどくわしくない場合にも有効 ムは ROM 化てきるて、しようか 0List 2 のプ て、す。 ログラムて、は変数 data はスタック上に領域 えが可能となります。 を確保します。スタックは当然 RAM て、すか バッテリノヾックアップ領域や定数領域の参照 ら , 書き換えは可能て、す。したがって List 2 のプログラムは ROM 化可能て、す。 て、は同じような List 3 のプログラムは ROM 化て、きるて、しようか 0List 3 の変数 data は初 期値をもったデータとなり , ROM 上に置か れるため書き換えがて、きません。したがっ て ROM 化て、きないことになります。 初期値をもつテータに 対処する方法 初期値をもったデータが書き換えて、きな いといわれても , 初期値をもった変数を使用 する場合もあるて、しよう。その場合には以 下のような対処法があります。 ( 1 ) 初期化関数で初期値を設定する List 4 のような初期化関数を作成して初期 Fig. 4 C M ー 68K の C コンバイラの メモリ配置 lSt / * 生産オータ・数 Max. * / . 1 : #define NMAX 1000 2 : #define FALSE 0 ( ! FÅLSE ) / * 真 * / 3 : #define TRUE 4 : 5 : struct mc=const { / * マシン定数 * / 6 : uns igned udatal : 7 : uns igned udata2 ; 8 : 9 : uns igned udatan : 12 : struct order { char cdatal[ 5 ] : char cdata2[ 5 ] : 15 : char cdatan[ 5 ] : unsigned udatal : uns i gned udata2; uns igned udatan : 20 : 22 : 23 : struct mc_const *pconst 24 : struct order *porder 25 : int flagl, fIag2; 26 : 27 : void func() 28 : { 29 : i nt n ; 30 : if ( pconst->udata2 flagl : TRUE; 32 : 33 : e 1 S e flagl ニ FA し SE; 34 : for ( n = 0 ; n く NMAX; n + + ) { if ( porder[ n ]. udata2 36 : fIag2 ニ TRUE; e 1 se 38 : fIag2 ニ FA し SE; 39 : 40 : 41 : 42 : } / * 生産オー第 * / / * 入力テ、、一タ ( ASCII ) * / ( struct mc-const * ) 0X10000 し : / * マシン定数 * / / * 生産オー * / ( struct order * ) 0X20000 い 下位アドレス TEXT セグメント (ROM) ニ 200 ) DATA セグメント (ROM) DATA セグメントに生成 List 6 BSS セグメント (RAM) : DATA セク・メント * / / * datal int datal 2 : 3 : int func() static int data2 20 : 5 : 6 : func2( "stringsYn" ) : return( 0 ) : 8 : / * data2 : DATA セク・メント * / : DATA セク・メント * / / * "stringsyn" スタック領域 (RAM) 上位アドレス 特集 ROM 化プログラミング考察 39

3. 月刊 C MAGAZINE 1990年11月号

DOS ヨールを使用している ーイプラリは使用できない ROM 化のプログラムて、はパソコンとは違 う構成になっているため , DOS 上とは別の 環境て、走行する場合も少なくありません ( Fig. 3 ) 。このようなシステムて、は , たとえば List 8 : 7 : 6 : 5 : 3 : 2 : BSS セグメントに生成 int datal; func() static int data2; return( 0 ) : i nt / * datal / * data2 Fig. 6 ROM 化時のメモリマップ 00000000 00000004 00000008 RAM ROM putchar( 'A' ) ; を使用すると DOS コールの 1 文字出力の機能 が呼び出されて , DOS コールが呼び出され た段階て、暴走してしまいます。 C 言語て、はラ イプラリが簡単に使用て、きるため , 無意識 のうちになじみの関数を使用してしまう場 合も少なくないて、しよう。このため LSIC-86 のように stdrom. h というへッダファイルを : BSS セメント * / : BSS セメント * / ( シャドウ ROM ) 番地に射影される 先頭の 8 ノヾイトが 0 ~ 7 リセット時だけ ROM の 通常の CPU ボードでは BSS セグメント スタック領域 イニシャル PC イニシャル SSP DATA セグメント TEXT セグメント ROM 化 考察 用意して , ROM 化可能なライプラリを明確 にしているコンパイラもあります。 また , ライプラリに関しては DOS コール 以外にも初期値をもったデータの書き換え やプログラムコード自体の書き換えなどを 行っているかどうかにも注意する必要があ ります。最近のコンパイラはある程度 ROM 化を意識している部分がありますから , DOS コールを使用していない関数て、は通常 ROM 化が可能なコードとなっています。 DOS コールを使用している ライプラリを使用する方法 どうしても DOS コールを使用する関数を 使用したい場合は C コンパイラのライプラリ のソースリストを別途購入して , ソースリスト を修正するのが確実て、しよう。 もうひとつの方法は ROM 化システム上て、 DOS コールをエミュレートすることて、す。 MS-DOS て、あれば , DOS ファンクションの INT21h をエミュレートすればほとんどのラ イプラリが使用て、きるようになります。し かし , このエミュレートはかなり大変て、す から , 実際は使用したいライプラリが使用 しているファンクションに的を絞って , 少 しずっ使用て、きるライプラリを増やしてい くことになるて、しよう。 0 イ可能なライプラリ ROM 化可能なライプラリは処理系によっ て異なりますが , 一般的に以下のライプラ リは ROM 化可能なはずて、す。 Table 1 に示 した以外て、も , それに類するものは ROM 化 可能なはずて、す ( ただし , ROM 化にあたっ てはその処理系ごとに確認してください ) 。 特集 ROM 化プログラミング考察 41 ロ

4. 月刊 C MAGAZINE 1990年11月号

プルーチンて、初期値を RAM 上に転送すると ンを行うことはないため , リンク時にリロ 化て、は通常 ROM と RAM は不連続て、あるた いうような細工を行わない限り , ROM 上に ケーション情報が生成されないようにリン め , コマンドファイルヘッダは ( B ) の形式に 置くことになります。 力のスイッチを指定します。 Fig. 5 からもわ なります。 BSS セグメント かるように BSS セグメントの領域は 68K ファ SENDC68 ユーティリティは . 68K ファイル 初期値をもたない変数が置かれる領域て、 イルの中には書き込まれておらず , 先頭ア のコマンドファイルヘッダから各セグメン す (List 7 ) 。この領域は RAM 上に置かれ , ドレスとバイト数がコマンドファイルヘッ トの先頭アドレスを取得し , TEXT セグメン CP / M ー 68K て、はスタートアップルーチンて、 ダに書き込まれているだけて、す。また , ROM トと DATA セグメントを S レコードに変換し BSS セグメントをゼロクリアしていますか ら , ROM 化の場合て、も通常はスタートアッ コラム 1 プルーチンて、ゼロクリアします。 スタック領域 スタック領域に関しては , スタックポイ ンタをスタートアップルーチンて、セットす るだけて、す。 C プログラムて、は表には出てき ません。しいていえば auto 変数がスタック 上に領域が確保されるくらいて、 , あとはサ プルーチンコールのように無意識のうちに 使用されます。 CP / M ー 68K て、はスタック領域を定義する 特別なセグメントがないため , BSS セグメン トの中にスタック領域を確保します。 上記以外にも ma Ⅱ oc 関数などて、動的にメ モリを獲得するためのヒープ領域があるの て、すが , ROM 化の用途て、はメモリ配置は固 定て、ある場合がほとんどて、すから , ほとん どの場合ヒープ領域は不要て、す。 CP / M ー 68K て、はリンカ (L068) て、 TEXT セグメント DATA セグメント BSS セグメント の 3 つの領域の開始アドレスが設定て、きるた め , システム構成にあわせてアドレスを決 定することがて、きます。リンカて、生成され た . 68K ファイルを SENDC68 ユーティリティ て、 S レコードに変換して ROM 化を行うこと がて、きます。 68 マンドファイル ォット Fig. 5 に 68K コマンドファイルフォー - ・マッ トを示します。 ROM 化の場合リロケー ショ 44 CMAGAZINE 1990 11 どのようなコーディングを行うと , どの セグメントが生成されるかを確認しておく ことは ROM 化にあたって必要です。このため にはコンバイラでアセンプリリストを生成 させます。たとえば , MS-C 5 コであれば /Fa をつけて List MS-C 5.1 テストプログラム ( testl . c ) コンヾイラの 生成セクメントの 確認 int near fpub; 2 : int near fpubdat 3 : int far ffarpub; 4 : int far ffardat ー int huge fhugepubC 0X8000 ] : 5 : 6 : int huge fhugedatC 0X8000 ] 7 : static int near fstat; 8 : static int near fstatdat 9 : static int far ffarstat; 1 0 : static int far ffarstatdat 11 : static int huge fhugestat[ 0X8000 ] : 12 : static int huge fhugestatdat[ 0X8000 ] 13 : 14 : const int near fpubcon const int far ffarcon ニ 10 : const int huge fhugecon[ 0X8000 ] static const int near fstatcon ニ 10 ; 17 : 18 : static const int far ffarstatcon 19 : static const int huge fhugestatcon[ 0X8000 ] ist Turbo C 2 ℃テストプログラム ( test2. c ) ーハ 4 れ一ハ丸ハ ・ハ人れ ーハーハ O みハ 4 ハ い 0 ー CO ーハー員ハ 0 ーハ 4 ハーハ・ハ人胤 ・ BSS を int near fpub; 'DATA' 2 : int near fpubdat 3 : int far *pfarpub; 'DATA' int far *pfardat 5 : i nt huge *phugepub : / * 'DATA' 6 : int huge *phugedat 7 : static int near fstat; 'DATA' 8 : static int near fstatdat 9 : static int far *pfarstat; 'DATAi 10 : static int far *pfarstatdat 1 1 : static int huge *phugestat; 12 : static int huge *phugestatdat ニ 13 : 14 : const int near fpubcon = 10 : ( int far * ) 0XC0000000 し : / * ・ DATA' const int far *pfarcon ( int huge * ) 0XC0000000 し : 'DATA ・ const int huge *phugecon 'DATA ・ 1 7 : static const int near fstatcon ( int far * ) 0XC0000000L : DATA' 18 : static const int far *pfarstatcon ( int huge * ) 0XC0000000 し : / * ' DATA' 1 9 : static const int huge *phugestatcon ( int far * ) 0XC0000000 し : ( int huge * ) 0XC0000000 し : ( int far * ) 0XC0000000 し : ( int huge * ) 0XC0000000 し :

5. 月刊 C MAGAZINE 1990年11月号

ROM 化 プログラミング 考察 ているだけて、す。 実際は以下のようなことを行います。 このとき List 8 のスタートアップルーチン ・スーバーバイザスタックポインタとプロ をほかのファイルよりも先にリンクして TEXT CP M 68K の C コンヾイラ グラムカウンタの初期値 セグメントを ROM の先頭に割り付ける必要 のタートアップレーチン スーパーバイザスタックポインタとプロ があります。 グラムカウンタの初期値はリセット時に 0 ~ 7 ・例外べクタテープルの設定 簡単なスタートアッフ。ルーチン例を List 8 番地 ( 通常はシャドウ ROM ) から読み込まれ バスエラー , アドレスエラーなどの例外や に示します。この例は非常に手抜きて、すが , ますから①のように設定します (Fig. 6 ) 。 ードウェア割り込みのためのべクタテー List1-C cl /c /Fa /AL /Gs test 1 . c のようにコンバイルし , TurboC 2.0 であれ ば -S をつけて tcc -c -S -ml test2. c のようにコンバイルします。 (List 1 -A, List I-B, List I-C, List I-D) 41 : P UBLI C ffardat 42 : PUBLIC fhugedat 43 : PUBLIC -fpubcon 44 : PUBLIC ffarcon 45 : PUBLIC fhugecon 46 : EXTRN -acrtused:ABS _BSS SEGMENT 48 : COMM NEAR _fpub: 49 : COMM FAR ffarpub: 50 : COMM NEAR -fhugepubt ENDS _BSS 52 : _DATA SEGMENT 53 : fpubdat DW ENDS 54 : _DATA SEGMENT 55 : TEST15_DATA $ + 2 56 : ORG ffardat DW ENDS 58 : TEST15_DATA 59 : TEST17_DATA SEGMENT 60 : fhugedat DW 00H 65534 DUP(O) DB 62 : 63 : TEST17_DATA ENDS 64 : -DATA SEGMENT 65 : $S107_fstatdat DW 66 : _DATA ENDS 67 : TEST15_DATA SEGMENT 68 : $S109_ffarstatdat 69 : TEST15_DATA ENDS 70 : TEST18_DATA SEGMENT 71 : $S111_fhugestatdat DW 65534 DUP(O) DB ー 74 : TEST18_DATA ENDS _DATA SEGMENT 76 : fpubcon DW _DATA ENDS 78 : TEST15_DATA SEGMENT 79 : ffarcon DW 80 : TEST15_DATA ENDS 81 : TEST19_DATA SEGMENT 82 : fhugecon DW 00H 65534 DUP ( の 83 : DB 84 : ENDS 85 : TEST19_DATA 86 : CONST SEGMENT 87 : $S115_fstatcon DW 0aH 88 : CONST ENDS 89 : TESTIIO_CONST SEGMENT 90 : $S116_ffarstatcon DW 91 : TESTIIO_CONST ENDS 92 : TESTIII_DATA SEGMENT 93 : $S117-fhugestatcon DW 65534 DUP ( 0 ) 94 : DB 95 : 2 BYTE: BYTE : BYT€: 2 65536 List 1 ー A のアセンプリリスト i st 0a 日 Static Name Aliases 2 : 3 : $S106_fstat $ S107 fstatdat 4 : $S108_ffarstat 5 : 6 : $S109_ffarstatdat 7 : $S110-fhugestat $ S111_fhugestatdat 9 : $S115_fstatcon $S116_ffarstatcon $S117_fhugestatcon TITLE testl. c NAME testl 14 : . 8087 16 : TESTI_TEXT SEGMENT WORD PUB い C 'CODE' 17 : TESTI_TEXT ENDS DATA SEGMENT WORD PUBLIC 'DATA' _DATA ENDS 20 : CONST SEGMENT WORD PUBLIC 'CONST' 21 : CONST ENDS 22 : BSS SEGMENT WORD PUBLIC 'BSS' 23 : _BSS ENDS 24 : TEST15_DATA SEGMENT PARA PUBLIC 'FAR-DATA' 25 : TEST15_DATA ENDS SEGMENT PARA PUBLIC 'FAR-DATA' 26 : TEST16_DATA 27 : TEST16_DATA ENDS 28 : TEST17 DATA SEGMENT PARA PUBLIC 'FAR_DATA' 29 : TEST17_DATA ENDS 30 : TEST18_DATA SEGMENT PARA PUBLIC 'FAR_DATA' 31 : TEST18_DATA ENDS 32 : TEST19_DATA SEGMENT PARA PUBLIC 'FAR_DATA' 33 : TEST19_DATA ENDS 34 : TESTIIO_CONST SEGMENT PARA PUBLIC 'FAR_DATA' 35 : TESTIIO_CONST ENDS 36 : TESTIII_DATA SEGMENT PARA PUBLIC 'FAR_DATA' 37 : TESTIII_DATA ENDS 38 : DGROUP GROUP CONST, _BSS, _DATA 39 : ASSUME CS: TESTI_TEXT, DS: DGROUP, SS: DGROUP 40 : PUBL'IC _fpubdat 0aH EQU EQU EQU EQU EQU EQU EQU EQU EQU fstat fstatdat ffarstat ffarstatdat fhugestat 、 fhugestatdat fstatcon ffarstatcon fhugestatcon 0aH DW 0a 日 00H 0aH 0aH 0aH 00H 特集 ROM 化プログラミング考察 45

6. 月刊 C MAGAZINE 1990年11月号

す。以下の Fig. 10 ようなコーディングを行 うとこのセグメントが生成されます。 初期値をもたない③と⑤が混ざっている ため , 対処が難しくなりますが , ③と⑤の 書式を使用しなければこのセグメントを ROM 領域に割り当てることにより対処可能て、す。 FAR DATA セグメントの初期値を ROM に置 いてスタートアップルーチンて、 RAM 上に転 送するツールもあるようて、すが , そこまて、 する意味があるかどうかは疑問て、す ( fa 「デー タにするということは合計て、 64K バイトを超 えるような配列の可能性が高いため , ROM Fig. 15 Fig. 16 ージモデルのセグメントの配置 下位アドレス DGROUP 上位アドレス ???—TEXT —DATA —BSS —STACK far ヒープ ヒュージモテルのセグメントの配置 下位アドレス ???—TEXT ???—DATA —STACK far ヒー ↓ 上位アドレス 'CODE' 'DATA' 'BSS' 'STACK' 'CODE' 'DATA' 'STACK' プ ファイルことに 64K 八イト以下 1- ー D S 64K バイト以下 ↓ SS 64K 八イト以下 ファイルことに 64K 八イト以下 ファイルことに 64K 八イト以下 64K ノヾイト以下 注 ) 1 . ? ? ? ー TEXT などの ? ? ? はファイル名になる。 2. ???_TEXT セグメント : プログラムコード た範囲が 64K 八イト以下の設定になる。 セグメントが DGROUP に属するが , ー STACK セグメントまてを含め 3. スモールモテルとミティアムモテルでは一 DATA セグメントと一 BSS トに組み込まれている。 ただし , ヒュージモテルは一 BSS セグメントか ? ? ? ー DATA セグメン —BSS セグメント : 非初期化テータ ???—DATA セグメント : 初期化テータ ROM 化 考察 プログラミン トて、す。以下のようなコーディングを行う 初期値をもたない HUGE データのセグメン HUGE BSS セグメント 利用することがて、きます (Fig. 11 ) 。 数用の ROM が離れた位置にある場合などに に割り付けることがて、きるため , マシン定 FAR DATA セグメントは任意のアドレス になります ) 。 と RAM に二重に割り付けられメモリが無駄 FAR BSS セグメント ります。 このセグメントは RAM 上に置くことにな int huge fhugepub [Ox8000] : とこのセグメントが生成されます。 特集 ROM 化プログラミング考察 49 なコーディングを行うとこのセグメントが 定数の nea 「セグメントて、す。以下のよう CONST セグメント る必要はありません。 から , 転送するプログラムを新たに記述す ルーチンのソースリストが付属しています す。 ROM 化ツールては通常スタートアップ ーチンて、 RAM 上に転送する必要がありま め , 初期値を ROM に置きスタートアップル このセグメントは DGROUP に属するた func( " DATA" ) ; static int nea 「 fstatdat=10 ; int near fpubdat=10 : このセグメントが生成されます。 て、す。以下のようなコーディングを行うと 初期値をもった neari•—タのセグメント DATA セグメント 11 ) 。 る領域などに使用すると便利て、す (Fig. て、きるため , 生産オーダをバックアップす ントは任意のアドレスに割り付けることが HUGE BSS セグメントと FAR BSS±グメ ります。 このセグメントは RAM 上に置くことにな int fa 「 ffa 「 pub ・ このセグメントが生成されます。 て、す。以下のようなコーディングを行うと 初期値をもたない fa 「データのセグメント

7. 月刊 C MAGAZINE 1990年11月号

C プログラムてはスタートアップルーチン から main 関数が呼び出されることになって います。 ROM 化システムて、も通常 , これに あわせてスタートアップルーチンから main 関数を呼び出します。このときスタートア ップルーチンはアセンプラて、記述しますか ら , 先頭にを付加します ( 注 1 ) 。 プルを設定します。 ・ BSS セグメントのゼロクリア ・ハードウェアの初期化 ・ユーザスタックポインタの設定 ・ユーザモードに切り換え ・ハードウェア割り込みの許可 ・メインルーチン main の呼び出し ( 注 1 ) c 言語とアセンプラのこの約束事は処理系 によって違います。たとえば MS-C,Turbo C,CP/M- 68KC などでは maln キー - → maln となりますが , LS ℃ー 86 では最後に一を付加して main ←ー→ main となります。また , OPT ー C86 では何も付加されず main + ー→ rnaln となります。 List1-D List1-C 36 : fpubcon label 10 38 : -pfarcon label 39 : 0 40 : dw ー 16384 phugecon label 42 : 0 dw 43 : dw ヨ 6384 44 : fstatcon label word 45 : 10 dw 46 : pfarstatcon label dword 0 dw 48 : ー 16384 dw 49 : phugestatcon label 50 : dw ー 16384 dw 52 : DATA ends 53 : _BSS segment word publ ic 'BSS' 54 : _fpub label word 2 dup ( ? ) 55 : db 56 : fstat 1 abel word 2 dup ( ? ) 57 : db 58 : _pfarpub label dword 4 d 叩 ( ? ) 59 : db 60 : -phugepub label dword 4 d 叩 ( ? ) db 62 : pfarstat label dword 63 : 4 d 叩 ( ? ) db 64 : phugestat b dword 65 : 4 d 叩 ( ? ) db 66 : _BSS endS 67 : ?debug C E9 68 : _DATA segment word public VDATA' 69 : s@ label byte -DATA endS 71 : TEST2_TEXT segment byte public 'CODE' 72 : TEST2_TEXT endS 73 : -phugestatdat phugestatdat equ -phugestatcon phugestatcon eq u 75 : _pfarstatdat pfarstatdat equ pfarstatcon pfarstatcon equ -phugestat phugestat equ 78 : -pfarstat pfarstat equ 79 : public -phugedat 80 : fstatdat fstatdat equ pub I i c -phugecon 82 : public -pfardat fstatcon fstatcon equ 84 : public -fpubdat 85 : public pfarcon 86 : public fpubcon 87 : pub I i c -phugepub public pfarpub 89 : fstat equ fstat 90 : public -fpub end word dword ENDS 96 : TESTIII_DATA SEGMENT 97 : _BSS DW 01H DUP ( ? ) 98 : $S106-fstat ENDS 99 : BSS SEGMENT 100 : TEST15_DATA ORG 101 : 102 : $S108_ffarstat DW 01H DUP ( ? ) ENDS 103 : TEST15_DATA SEGMENT 104 : TEST16_DATA 105 : $S110_fhugestat DW 08000H DUP ( ? ) ENDS 106 : TEST16_DATA 107 : END dword dword 0 List 1 ー B のアセンプリリスト lSt ifndef ??version 2 : ?debug macro 3 : endm 4 : end i f ?debug S "test2. c" 6 : TEST2_TEXT segment byte public 'CODE' 7 : DGROUP gro 叩 DATA, _BSS assume cs:TEST2_TEXT, ds:DGROUP 8 : 9 : TEST2_TEXT endS segment word public 'DATA' DATA 1 1 : d@ label byte 12 : d@w bel word 13 : DATA ends segment word public 'BSS' -BSS 15 : b@ label byte 16 : b@w label word ?debug C E9CE7Al 1150774657374322E63 17 : _BSS endS 19 : _DATA segment word publ ic 'DATA' 20 : _fpubdat label word 10 dw 22 : -pfardat ね b 引 dword 23 : 0 dw ー 16384 24 : dw 25 : label phugedat 0 26 : dw ー 16384 27 : dw label 28 : fstatdat 10 dw 30 : pfarstatdat label 0 dw 32 : ー 16 384 dw 33 : phugestatdat label 34 : dw ー 16384 35 : dw dword word dword dword 0 46 CMAGAZINE 1990 11

8. 月刊 C MAGAZINE 1990年11月号

List 9 EXE ファイルヘッダのオフセット 14h ~ 17h に書き込まれます。 EXE ファイルから HEX フォーマットに変換する ROM 化ツールはこ の情報から FFFF0h の位置に ( たとえば JMP FARPTR STARTUP のような ) fa 「ジャン プ命令を自動的に生成してくれます ( OBJ フ ァイルをリンクして HEX フォーマットに変 換する ROM 化ツールの場合にはこの情報を OBJ ファイルから読み取ります ) 。 テ叭、のについて DOS のプログラムのデバッグに関しては とくに説明の必要はないて、しよう 0MS-DOS DEBUG → SYMDEB CodeView と進化し , 最近はほとんどの C コンパイラて、 ソースデバッガが標準て、付属しているか , または , 別売りて、入手可能て、す。 ROM 化プ ログラムのデバッグて、はターゲットの ROM 化システムが開発マシンとは異なるため , デバッグが難しくなります。 しかし , ROM 化システムのデバッグて、も これらの DOS 上のデバッガを利用すること も少なくありません。どういうことかとい うと , 入出力と関係のない部分のアルゴリ ズムの検証や入力データをファイルから入 力して , 出力データをファイルに出力する などして実際の入出力とは切り放してデバ ッグを行うわけて、す ( Fig. 19 ) 。こうすれば DOS 上のプログラムとしてある程度のとこ ろまて、はデバッグて、きるようになります。 この方法の最大の利点は高機能な DOS 上 のソースデバッガが利用て、きることて、す。 しかし , 実際のリアルタイムなデバッグは 行えないため , 通常は以下の方法を使用 ( 併 用 ) することになります。 ( 1 ) ℃ E()n Circuit Emulator) その昔は ROM 化システムのデバッグとい えば ICE という高価なシステムて、行っていま 52 CMAGAZINE 19 11 ( start of STACK ) 17 : ;extrn 18 : e nd i f _main:far 20 : 21 : RTM_TEXT segment word publ ic 'CODE' 22 : RTM_TEXT ends 23 : i f C-CompiIer eq MSC 24 : FAR_DATA segment para public 'FAR_DATA ・ 25 : FAR_DATA ends 26 : e nd i f 27 : RTM_DATA segment para public 'DATA' 28 : RTM_DATA ends 29 : DATA segment word public 'DATA' 30 : _DATA endS C-CompiIer eq MSC 32 : CONST segment word public 'CONST' 33 : CONST ends 34 : end i f 35 : _BSS segment word publ ic 'BSS ・ 36 : BSS endS 37 : C-CompiIer eq MSC 39 : STACK segment stack 'STACK' 40 : STACK endS 42 : DGROUP GROUP RTM_DATA, _DATA, CONST, 43 : 44 : STACK segment stack 'STACK' ( STKSIZ / 2 ) dup ( ? ) 45 : dw 46 : SYSSP label word 47 : STACK endS 4 8 : end i f C-Compi ler eq TURBOC 49 : i f 50 : STACK segment stack 'STACK' STACK ends 52 : 53 : DGROUP GROUP RTM_DATA, _DATA, 54 : 55 : STACK segment stack 'STACK' ( STKSIZ / 2 ) dup ( ? ) 56 : dw 57 : SYSSP label word 58 : _STACK ends 5 9 : end i f 60 : 61 : RTM_TEXT segment word public 'CODEi 62 : assume cs:RTM_TEXT 63 : 64 : sp_reg dw DGROUP:SYSSP 65 : ss_reg dw DGROUP 66 : ds-reg dw DGROUP 67 : スタート・アッフ・ルーチン 68 : 69 : 70 : i n i t 71 : 72 : 74 : 75 : 76 : 77 : 79 : 80 : 82 : 83 : 85 : 86 : 88 : 89 : 90 : end:byte : end of BSS extrn BSS, STACK て、は -BSS 。家′、ノ、ノ ・ト′ー 0 ノ 工お、、・て 「人「ム一ア far SSi cs: [ss_reg] sp, cs: [sp_reg] proc mov tTlOV c 届 RAM クリア 、ノ ツツ、り′ 、おし、ノ ツツ冂′ d i , d i xor es,di es : d i ITIOV cx,RAMSIZE * 8 : RAM ワード数 xor ax, ax stosw : RAM クリア rep DGROUP 初期値 ROM → RAM 転送 RAM 先頭アドレス 割込へ・クタたガルの設定

9. 月刊 C MAGAZINE 1990年11月号

次の先頭位置 pout next となっています。 list3. srt の 2 行目の数 data ( 44 行目 ) と文字列 buf ( 45 行目 ) を読み込みます。 内側ループの次の位置 pin next を確保しま す ( 46 行目 ) 。 data と bigge 「を比較して ( 47 行 目 ) , もし data のほうが大きかったら , pout の位置に data と buf を書き込み ( 48 , 49 行 目 ),pin の位置に bigger と big_buf を書き込 みます ( 50 , 51 行目 ) 。さらに , bigger と big buf のそれぞれに data と buf を代入して極大 値を更新します ( 52 , 53 行目 ) 。そして , 46 行目て確保した pin next を用いて , ファイル を元の位置 , つまり内側ループの次を指す ように設定します ( 54 行目 ) 。 これて、 , 単純選択ソートの内側のループ のファイル位置が , 次の位置 ( 行 ) を示すよ うになります。この処理を EOF まて、繰り返 すことにより Iist3. srt の第 1 行目には最大値 のデータが入ることになります。 内側のループを抜けた後 , ファイル終了 指示子の EOF 指示をクリアします ( 58 行 目 ) 。次に , 前に保持しておいた pout next を用いて , 外側のループて list3. srt の次の行 ( 2 行目 ) を指します ( 59 , 60 行目 ) 。 29 行目の fo 「ループて , list3. srt が i 行あることが求め られているのて , この外側ループを i ー 1 回繰 り返せばソートてきるのてす ( 38 行目 : i は i をデクリメントした値が式の値てすね ) 。 最後にファイルをクローズして , プログ ラムを終了します ( 63 , 64 行目 ) 。 関数 e 「「はプログラムの使用法を標準工ラ ー出力に出力してプログラムを終了します ( 68 ~ 81 行目 ) 。プログラム名を出力する際 に , 語尾 ! EXE" を削除しています。 関数 enter space は文字列の後ろにスペー スを埋め込み文字列 n 〃を含めて MAX ー 1 行にします ( 84 ~ 94 行目 ) 。 関数 fscanf について 文字列を入力するときに , fscanf("%d %s" &data, buf ) ; としなかったのはなぜてしょラか。わざわ ざ fge 熔を用いたのには理由があります。関 126 CMAGAZINE 1990 11 List 3 83 : / * スペースを埋め込む関数 enter_space * / 84 : void enter_space( char *s ) 86 : 88 : 89 : 90 : 92 : 93 : 0 0 i 十十 , S 十十 ) ー 2 : i 十十第 S 十十 ) = 0 : く MAX / * 改行コード ' Yn ' の付加 * / / * 文字列の終わり ( ・ \ 0 ・の付加 ) * S 十十 Fig. 3 単純選択ソート ( List 3 37 ~ 61 行目 ) big buf bigger 39 行目 40 行目 4 : 8 : 6 2 ー 4 ー K : u :mti : k : 0 ー 0 ー t : 0 : 44 行目 45 行目 data buf 47 行目で data と bigge 「の比較 , data のほうが大きいので pout の位置に data と buf を書き込む ( 48 ~ 51 行目 ) pin の位置に bigger と big-buf 外側ループ 1 内側ループ 2 内側ループ 1 外側ループ 1 pout 41 , 42 行目 P1n pout- next pi n-next bigger 52 行目 2 : 4 : 6 : 8 : 0 い 2 K ー u lm ⅱー k ー 0 ーー G ー 0 ー t ー 0 ー T ー 0 ー s : h : i 45 行目 44 行目 buf data このようにして 44 ~ 57 行目のループで一番大きいテータ bigge 「と big-buf を求める 外側ループ 2 内側ループ 1 / big-buf 53 行目 pout pout- next Ptn pi n-next ら 6 行目 46 行目 bigger 39 行目 big-buf 40 行目 4 : 6 : 8 0 : 4 い 2 K ー u lmli ー k ー 0 ーー G ー 0 ー t ー 0 lTlo Ⅲ : リ■ k 0 IT : a : h l,a : 「 45 行目 44 行目 data buf pout の位置をすらして 44 ~ 57 行目のループ処理を行うと大きい順に並び換 えが完成する 60 行目 41 , 42 行目 46 行目 pout Pln pout-next pin-next

10. 月刊 C MAGAZINE 1990年11月号

からないが , 一連のアドレスに配置された TLINK のマップファイルと比べれば , コン フィグレーションファイル ( ターゲットボー ドのメモリ構成 ) に従って各クラスが配置さ れているのが確認て、きる。 LOCATE の絶対セグメントマップの最後 (ABSOLUTE) ??BOOT というセグメントが LOCATE によって自動 生成されているのに気づかれただろうか。 , こにはアプリケーションのスタートアッ プコードのある開始アドレス F0000 への fa 「ジ ャンプ命令が自動生成される。したがって , リセットをかけると自動的にアプリケーシ ョンのスタートアップを実行するのて、 , プ ログラマは , CPU の立ち上げに関してとく に配慮する必要はない ロケーティングの基本理論は以上て、十分 もちろんロケータを自作する場合 だろう。 は HEX フォーマット形式を勉強しなければ ならない 日 0 M 化の手順 1 ) プログラムを書く 2 ) LOCATE に付属の makefile の修正 3 ) makefile の実行 4 ) デバッガを使って実行 5 ) HEX ファイルを生成し ROM ライタで ROM 焼き付け C プログラムを ROM 化する際には , て、き るかぎり単純なコードから試してみるのが よいだろう。単純というのは , 動作するコ ードすべてをプログラマ自身て、書いたプロ グラム , いい換えれば , ランタイムライプ ラリをまったく使わない , かっ正常に動作 していることを容易に確認可能なプログラ ムて、ある。 たとえば , main( ) { int a ; lSt LOCATE コンフィグレーションファイル : RAM の存在しない領域指定 : 初期化データの自動生成 : F 圓 00H からロード : DATA クラスは 00400H から : RA M クラス順序構成 : STACK に続けて Farheap を配置 : ROM クラスの構成順序 0X10000 0xeffff reserve DATA ROMDATA dup CODE = 0Xf000 class DATA = 0X0040 class DATA BSS BSSEND STACK order STACK FARHEAP order CODE INITDATA EXITDATA order EXITDATA ROMDATA ENDROMDATA order ファイルへ出力するクラス CODE INITDATA EXITDATA ROMDATA : rom lSt T 凵 NK の出力した相対アドレスマップ 00000H 000 圓 H 00000H BEGTEXT 00000H 000A4H 000A5H -TEXT 000A5H 000F9H 00055H SI EVE-TEXT 00100H 00100H 00000H BEGINIT 00100H 00100H 00000H j„INIT_ 00100H 00100H 00001H _INITEND- 00102H 00102H 00000H _EXIT_ 圓 102H 00102H 00000H _EXITEND- 00110H 00110H 00000H ROMDÅTA 00110H 0011FH 00010H ERDATA 00120H 圓 120H 00000H BEGDATA 00120H 00120H 00000H _DATA 00120H 0211FH 02000H _BSS 02120H 02121H 00002H -BSSEND 02130H 0252FH 00400H STACK 02530H 02530H 00000H FARHEAP CODE CODE CODB INITDATA INITDATA INITDATA EXITDATA EXITDATA ROMDATA ENDROMDATA DATA DATA BSS BSSEND STACK FARHEAP LOCATE が変換した絶対アドレスマップ ←イントべクタの直後 DATA DATA BSS BSSEND STACK FARHEAP CODE CODE CODE INITDATA INITDATA INITDATA EXITDATA EXITDATA ROMDATA ROMDATA ROMDATA ENDROMDATA (ABSOLUTE) 00400H 00400H 00000H BEGDATA 00400H 00400H 00000H -DATA 00400H 023FFH 02000H -BSS 02400H 02401H 00002H _BSSEND 02410H 0280FH 00400H STACK 02810 日 0281 囲 00000H FARHEAP F0000H F0000H 00000H BEGTEXT F0000H P00A4H 000A5H _TEXT F00A5H F00F9H 00055H SIEVE_TEXT F0100H F0100H 00000H BEGINIT F0100H F0100H 00000H _INIT_ F0100H F0100H 00001H -INITEND_ F0102H F0102H 00000H _EXIT_ F0102H F0102H 00000H _EXITEND- F0110H F0110H 00000H ROMDATA F0110H F0110H 00000H BEGDATA F0110H F0110H 00000H _DATA F0110H FOIIFH 00010H ERDATA FFFFOH FFFF4H 00005H ??BOOT ← ROM 領域開始 66 CMAGAZINE 1990 11