C compiler system  X1 用の C コンパイラーが完成しましたので「第5回I/Oプログラムコンテス ト(第2次募集)」に応募します.  一般的にパソコンで C 言語を動かすためには、フロッピーディスクと CP/M 等の OS を必要とし、それなりの投資が必要です.  今回、作成したコンパイラーは、X1 本体とディスプレイの基本構成のみで動 作しますので手軽に C 言語の雰囲気を楽しめるものと思います.ただ、基本構 成で動かすためにテープシステムとなっており、操作牲が若干劣るのは仕方な いこととおもいます.  本コンパイラーには、次のカセットテープをセットしています.  @C system(BASIC CZ-8CBOlより起動)     テープ1  AC system(IPLより起動)           テープ2  BC stdfunc.c  (標準関数)        テープ3  Cmemory dump.c (デモプログラム)     テープ4  本コンパイラーシステムには、C ソースプログラムを作成するエディタ、コ ンパイラー本体、ならびにコンパイルオブジェクトであるアセンブラソースを 編集・アセンブルするエディタ・アセンブラの各システムプログラムが組み込 まれています.  エディタ・アセンブラは、独立したアセンブラとしての使用も可能となって います.  これらのシステムプログラムは、テープから一括してメモリにロードします ので、C プログラムの作成・コンパイルの過程でシステムプログラムをロード し直す必要はなく、操作性が良くなっています.  本コンパイラが取り扱う C は整数型のサブセット仕様となっていますが、C の入門用としては充分使用できるものと思います.アセンブラにおいては、一 般的なザイログ形式のニーモニックを使用しています.  それでは、使用方法等順次説明します. コンパイラーシステムの起動  コンパイラーシステム(以下 C-system と呼ぶ)の起動は、次のようにして 行います.  @ BASIC CZ-8CBO1 を立ち上げます.  A MON でモニタに行き、テープ1 のプログラムを L コマンドで読み込みま   す.  B 次に、Mコマンドで、012BH を A3H に、012CH を 14H に書き換えます.  C S コマンドで、    *S 0000 87FF 0000:C system   として新しいテープにセーブします.  D このようにしてセーブしたテープを IPL からロードすれば、C-system が 起動します.  テープ2には、すでにこのようにして作成した IPL より起動するプログラム が納めてあります. C system の動かし方  C system が起動すると、オープニングメッセージが表示され、">" のプロン プトが出力され入力待ちとなります.ここで、    >ed と入力すると、C-editer が起動されます.  C-editer が起動すると、オープニングメッセージの後、"$" のプロンプトを 出力し入力待ちとなります.  C-editer の i コマンド等で C のソースプログラムを作成します.プログラ ムの作成が終われば、! コマンド C-system に戻ってください.  C-system に戻れば、つぎに、    >c -lc と打ち込みコンパイルを行います.コンパイルエラーがあった時は、再度 C-editer を起動し、ソースプログラムの修正を行ってください.C-editer で 作成したソースプログラムは、意識的に削除しない限り保存されています.  修正が終われば、再度コンパイルを行い、エラーが無くなった段階で、    >c test.c -lctm9000 と打ち込んで、新しいテープにコンパイルオブジェクトを出力させます.  つぎに、    >ea と打ち込んで、C-editer & assembler を起動させます.  C-editer & assembler が起動しますと、"#" のプロンプトが出力されますの で、    #r "test.c" と入力して、先ほど作成したオブジェクトテープを読み込ませます.読み込ん だオブジェクトは単なるアセンブラソースと同じですから、これ以降は、 C-editer & assembler のエディタにより、自由に変更、最適化、アセンブラ関 数の組み込み等、手を加えることも可能です.  つぎに、    #a と打ち込んで、アセンブラを動かしアセンブルします.Pass1, Pass4 にてアセ ンブルされたアセンブルオブジェクトは、    ]r と打ち込むことにより、直ちに実行させることができます.  オブジェクトの実行によりシステムの管理を離れますので、オブジェクトの 格納番地や実行後の管理には注意してください.  通常は、オブジェクは 4000H 番地以降に生成(org 4000H の疑似命令を置く )させるとともに、実行後は X1 monitor の開始番地である 1000H に飛び込む ようにします.こうしておけば実行後は、背面のりセットスイッチを押すこと により C-editer & assembler に戻ることができます.C-system には、! コマ ンドにて戻ることができます.  以上簡単に、コンパイラシステムの動かし方について説明しましたが、各プ ログラムの詳細なコマンドについては、それぞれのコマンド説明の項を参照し てください. C syntax について  本コンパイラの扱う C の syntax について、説明します.冒頭に述べました ように、整数型のサブセットであることのほか、その他の点でフルセット C と は差異があります.フルセット C との差異を中心に順次説明します.なお、最 近のANSIの標準規格については一切考慮してありません.  サブセット C ではありますが、文の処理、複雑な型宣言、配列、ポインタ、 構造体、共用体、などにおいては、出釆る限りフルセット C の機能を実現して います. (1)語句   @ コメント     コメントは、入れ子が可能となっています.   A 識別子とキーワード     識別子は、英数字で構成され、先頭は英字で始まらねばなりません.    "_" は、英字とみなされます.有効なのは先頭の 8 文字までです.     キーワードには、つぎのものが予約されています.なお、先頭にキー    ワードを含む識別子は、キーワードとはみなされません. if long *entry return switch unsigned do auto *short sizeof ifndef *register int goto *float static define continue for case union *double endasm asm else ifdef struct typedef char while endif extern default     キーワードには、機能をサポートしていないものも含まれています.            (* 機能サポートなし)   B 定 数     数字列からなる整数定数は、先頭に 0X、または 0x が付けば 16 進定    数、0 が付けば 8 進定数であり、それ以外は 10 進定数です.     整数定数の取り得る債は、-32768〜+32767、または、0〜65535 であ    り、2 バイトの大きさとなっています.     8 進数は、0〜7 ではなく 0〜9 も 8 進数として処理しますので注意    してください.     単一引用符で囲まれた文字定数の内、サポートしているエスケープ文    字には、次のものがあります.     '\r'...復帰 (0x0d)  '\b'...バックスペース (0x08)     '\t'...タプ (0x09)  '\n'...復帰改行 (0x0d)     '\f'...ホーム (0x0b) '\c'...画面消去 (0x0c)     さらに、\ 記号に続けて A〜Z を記述すると、X1 の画面コントロール    コードに変換されます.¥ 記号に続く 3 文字内の数字は、ビットパタ    ーンとして任意の文字が指定できます.それ以外は、¥ 記号は無視され    ます.     浮動小数点定数は、ありません.   C 文字列     二重引用符で囲まれた文字列であり、行の終わりに ¥ を付けること    によって 2 行以上に渡って記述することができます.     なお、コンパイラの処理する 1 行は、継続行であっても 256 文字ま    でですので、その範囲内で記述します. (2)記憶クラスと型   @ 記憶クラス     記憶クラスとしては、次のものが使用できます.       auto, static, extern, register     register記憶については、autoとまったく同じに扱われます.記述し    てもエラーとはならない程度にしか扱われていません.   A 型     使える型は、次のとおりです.       char, int, unsigned, long, short, typedef名     ここで、typedef 名は、typedef により予め型宣言された識別子をい    います.long,short については、常に 16 ビットで扱いますので、記    述してもしなくても同じ結果となります.unsigned,long,short は形    容詞的に unsigned int などと宣言することもできます.     char については、常に 8 ビット正整数であり、式の中で int に変換    されたときも正整数となります・(上位パイトに 00 を付けるだけ)   B 型宣言     上記型を基本として、それから派生するものとして       ポインタ、配列(多次元可能)、関数ポインタ、配列ポインタ       構造体、共用体、等    の型宣言を行うことができます.さらに、これらの型宣言は、宣言の許    される所ではどこでも宣言できます.関数内のブロックの先頭での変数    宣言ももちろん可能です.宣言の適用範囲は、一般的な規則に従います.     構造体、共用体の宣言で、タグ名やメンバ名は、通常の変数名と重複    しても構いませんが、異なる構造体、共用体において同一メンバを使用    しても区別されず、アドレスオフセッットは、先に宣言されたものが使    用されます.構造体、共用体の入れ子宣言についても特に制限はありま    せん.なお、ビットフィールドの宣言はできません.   C 初期化     変数宣言における初期化については、今回サポートされていません.     この機能は、ぜひとも設けたいとおもったのですが、コンパイラの宣    言処理の設計で初期化について当初考慮していなかったため、現パージ    ョンでの変更が簡単にできず諦めたためです. (3)式    フルセット C と同様の式が記述できます.細部について、とくに注意す   る点を取り上げて説明します.   @ 使用できる演算子、結合規則、優先順位は、フルセット C と同じ仕様    となっています.   A シフト演算の右シフトでは、符号付きならば符号ビットが、符号なし    ならば 0 が第 15 ビットに入ります.   B 単項演算の "+" は、ありません.   C 条件式の持つ型については、式中に記述される 3 つの式の型の一致の    チェックをしていないため、どのような式を置いても良く、その結果と    しては不定となっています.   D 代入演算式の複合演算子は、=*, =+ のような 2 項演算子が後にくる    ものは使用できません.   E sizeof 演算において、       sizeof(関数名)    としたときは、関数の返す型のサイズが値となります.   F 代人演算式の右演算数に、構造体変数(メンバ指定なし)を置いたと    き、代入されるのは、その変数のアドレスとなります.(構造体全体の    代入はできません.)   G 式における被演算数の型の一致のチェックは、厳密に行っていません    のでキャストによる明示的な型変換をしなくてもコンパイルエラーとは    なりません.次の、例のような場合にキャストを使うとコーディングが    少なく便利かとおもいます.     (例)0x0006 番地を 0x50 に変更する.      < 通常 >       < キャスト使用 >      char *p;        p = 0x006;    *((char *)0x006) = 0x50;        *p = 0x50;   H 演算の結果引き起こされる通常の算術変換については、float, double    への変換が無いだけで、一般的なものと同じ変換がされます.なお、ポ    インタは、基本的に符号無し整数で扱われます.   I 論理演算では、フルセット C と同じく、左側の式の結果によっては右    側の式の評価はされません.   J p[] で宣言されたものは、*p と宣言されたものと同じであり、p への    代人演算はゆるされます.      int p[];       int p[20];        p = 0x2000;      p = 0x2000;      (エラーとならない)  (左辺値エラーとなる)   K 宣言されていない関数が現れた時は、型が int であるものとしてコン    パイルします.   L 関数の引数は、右側から左に向かって評価します.     コンパイラの本処理において、処理が簡単になるよう関数の引数列は     1 行以内に記述されてあるものとの前提条件を設けています.このた     め、引数列は、必ず一行に納めてください.   M 配列等の添字付き演算では、それらは、ポインタ演算に置き換えてコ    ンパイルしていますので、次のように変則的な記述をしても正しくコン    パイルされます.      < 通常の記述 >  < 変則記述 >       a[x]; x[a];       b[y][z]; y[b][z]; z[y[b]];   N C では、ポインタ演算と配列の添字演算は同じものですから、次の、    記述 a、記述 b の表現はまったく同じとなります.      < 記述 a >       < 記述 b >       c = *(a[2]+3); c = (*(a+2))[3];   O 多次元配列においては、代入が許されるのは最終の添字計算をされた    オブジェクトのみで、それ以前は次に続く配列のアドレスであり、代人    は許されません.        char a[10][20][30]; a = 10;     ------- エラーとなる a[x] = 20;    -------  同上 a[x][y] = 30; -------  同上 a[x][y][z] = 40; ------ エラーでない   P 定数式の記述は、整数定数、文字定数、sizeof 式による四則演算等で    構成されますが、論理演算式、条件式による記述はできません. (4)文    文についてもフルセット C と同様以下の文が使用できます.     空文、式文、複文、if〜else、while、do〜while、for     switch、case、default、break、continue、return、goto     名札付き文    これらの中で、特に注意すペきものについて説明します.   @ 複文の先頭では、局所変数や型宣言を行うことができます.   A continue は、switch 文の中で使用したときlま、その switch を含む    ループの終わりに制御を移します.switch がループの中になければエラ    ーとなります.   B goto 文の飛び先は、その関数内にかぎります.なお、飛び先の名札付    き文が記述されなかった時は、コンパイルの段階ではエラーが出力され    ず、アセンブルの段階で未定義エラーが出力されます.   C 名札付き文の名札は、異なる関数では同じものを使用してもかまいま    せん.また、名札に用いる識別子は変数名等と重複してもかまいません.    関数内で、同じ名札を重複して使用すると、コンパイルの段階ではエラ    ーが出力されず、アセンブルの段階で多重定義エラーが出力されます.   D 名札付き文は、goto 文の有無にかかわらず記述しても構いません. (5)ブリプロセッサ    本コンパイラの持っているブリプロセッサ機能について説明します.   @ #define 識別子 綴り文字列     文字列置換については、単純に識別子を綴り文字列に置換するだけで、    引数付きマクロはありません.置換文字列に対して再置換しませんので    注意してください.   A #undef 識別子     定義済識別子を無効にします.   B #if 定数式 〜 #else 〜 #endif     #ifdef    〜 #else 〜 #endif     #ifndef   〜 #else 〜 #endif     条件付きコンパイルの制御をおこないます.機能としては、一般杓な    ものですので特に説明を要しないとおもいます.   C #asm 〜 #endasm     インライン・アセンブルの機能であり、#asm と #endasm で挟まれた    行は行頭のスペースが削除されるだけで、そのままコンパイル出力とし    て出力されます.     アセンブラ言語による関数などは、ここに書くことができます.    テープシステムによるコンパイラですから、#include の機能は設けてい   ません. 標 準 関 数   本コンパイラシステムでは、テープ 3 に C ソースプログラムの形で幾つ  かの関数を納めています.ここでは、簡単な説明にとどめますので、詳細に  ついてはプログラムを見て頂ければ結構かとおもいます.   @ strlen(s) char *s;      文字列の長さを返します.   A strcpy(s1,s2) char *s1,*s2;      文字列を複写します.   B strncy(s1,s2,n) char *s1,*s2; int n;      n 文字だけ文字列を複写します.   C strcat(s1,s2) char *s1,*s2;      文字列を連結します.   D strncat(s1,s2) char *s1,*s2; int n;      n 文字だけ文字列を連結します.   E strcmp(s1,s2) char *s1,*s2;      文字列の比較をします.   F strchr(s,c) char *s,c;      文字列 s の中の、文字 c の、左側からの最初の位置を返します.   G strrchr(s,c) char *s,c;      文字列 s の中の、文字 c の、右側からの最初の位置を返します.   H isdigit(c) char c;      文字 c が、10 進数字かどうかチェックします.   I isxdigit(c) char c;      文字 c が、16 進数字かどうかチェックします.   J isupper(c) char c;      文字 c が、英大文字かどうかチェックします.   K islower(c) char c;      文字 c が、英小文字かどうかチェックします.   L isalpha(c) char c;      文字 c が、英字かどうかチェックします.   M isalnum(c) char c;      文字 c が、英字か 10 進数字かどうかチェックします.   N toupper(c) char c;      英小文字を英大文字に変換します.   O tolower(c) char c;      英大文字を英小文字に変換します.   P atoi(s) char *s;      10 進数字文字列を、整数に変換します.   Q open(name,mode) char *name; int mode;      ファイルをオープンします.      ファイル名の先頭には必ず、次のデバイス指定をつけます.       cas: カセットテープ       lpt: プリンタ装置       key: キーボード       scr: 画面       crt: 画面(コントロールコードの制御無し)      オープンモードは、0(読み込み)、1(書き込み)となっています.   Q read(fd,buf,size)int fd,size; char *buf;      fd で示すファイルから buf に、size 分だけの文字を読み込みます.   S write(fd,buf,size) int fd,size; char *buf;      fd で示すファイルに、buf から size 分だけの文字を書き込みます.   ○ close(fd) int fd;      fd で示されるオープン中のファイルをクローズします.   以上の関数は、C-editer にて読み込んだ上、必要なものを取り出して使用  します.   これらの関数の他に、C-system のランタイムルーチンの中に次の関数が組  み込まれています.ランタイムルーチンに組み込みですので関数処理をプロ  グラミングする必要はありませんが、使用するにあたっては、int 型以外の  ものは、プログラムの中で extern による関数の型宣言をしておく必要があ  ります.   @ int getchar()      キーボードから 1 文字読み込みます.   A putchar(c) char c;      画面に文字 c を表示します.   B char *gets(s) char *s;      キーボードから文字列を入力し、バッファ s に格納します.   C puts(s) char *s;      画面に文字列を表示します.   D printf(s,n1,n2,...) char *s;      画面に書式を付けて、表示します.   E scanf(s,n1,n2,...) char *s;      キーボードより書式付き入力を行います. C editer & assembler   assembler syntax  C editer & assemble におけるアセンブラーは、以下に述べるシンタックス のテキストをアセンブルします.ニーモニックコードは、一般に使用されてい るザイログのオペコードと同じです.オペコードやレジスタ名は大文字、小文 字どちらで記述されていてもアセンブルできます. (1)書 式     ラベル: オペコード オペランド ;コメント    1 行には、ラベル、オペコード、オペランド、コメントが記述されます.   ラベルの終わりには:(コロン)、またコメントの先頭には;(セミコロ   ン)をつけます.オペコードとオペランドの区切りにはスペースをもちい   ます.    空白行やラベルのみの行も許されます. (2)規 約   @ ラベル     ラベルは8 ビット、16 ビットのデータや、アドレスに使用します.     ラベルには次の文字を除き自由に記述できますが、長さは 8 文字以内    に制限されています.また、先頭に数字は使用できません.    (使用禁止文字)      +, -, *, /, (, ), $, ;, :, ', ", (カンマ), (スペース)  オペコードやレジスタ名と同じラベル名を記述しても構いませんが、そ    のラベルを参照する場合、オペコードやレジスタとして意味があるよう    に解釈可能な時は、オペコード、レジスタを優先しますので、そのつも    りで記述してください.   A オペコード     オペコードには、後で述べる疑似命令も含みます.オペランドを必要    とする場合、区切りにスペースを使用します.   B オペランド     オペランドは、命令によっては 2 個必要とするときがあり、その時オ    ペランドは、,(カンマ)で区切ります.     オペランドには、ラベルが指定でき、さらに、ラベルと整数、ラベル    とラベルの加減乗除算ができます.演算子の優先順位は無く左から右に    順に演算されます.   C コメント     行の先頭に ; を付けると、その行はすペてコメント行とみなされます.    また、オベコードやオペランドの後に;を付けるとそれ以後はコメント    とみなされます.   D 定  数     オペランドに使用する定数には、10 進、16 進、文字列の各定数があ    ります.数字の最後に H(h)を付けると 16 進、’(アポストロフィ)    で文字列(1文字も可能)を囲ったものは、その文字のアスキーコード列    が定数となります.     a〜f で始まる 16 進定数を記述する時には、ラベルと区別するため先    頭に 0 をつけます.   E アドレス     オペランド記述における各アドレッシングモードにおいて、それぞれ    ラベルや定数を記述することができます.また、それらの演算結果をア    ドレスとすることもできます.     相対分岐命令においては、-126〜+129 までの範囲内にアドレスが生成    され無かった場合にはエラーとなります.     当該命令の生成されるアドレス(ロケーションアドレス)を参照する    場合には、$ 記号を使用します.   F 疑似命令     疑似命令には、次のものが用意されています.各疑似命令の n,nn は    オペランド指定であり、オペランドにはラベルや定数、その演算を記述    できます.     org  nn  オリジン.アセンブルの開始アドレスを治定します.テ           キストの途中でこの命令が現れた時には、ロケーション           カウンターの保持アドレスを、強制的に指定アドレスに           変更しアセンブルを続行します.この時、アドレスが後           方に戻るような指定がされた場合には、エラーとなりま           す.テキストの先頭にこの命令が置かれていない時は、           2000h 番地よりアセンブルします.     equ  nn  イクエイト.ラベルに値を定義します.定義される値は、           データ、アドレスどちらでも構いません.     defb  n  デファインバイト.この行のある位置に、オペランドで     (db)    示される 1 バイトを置きます.複数のオペランドをカン           マで続けて記述することもできます.     defw  nn  デファインワード.この行のある位置に、オペランドで     (dw)    示される 2 バイトを置きます.複数のオペランドをカン           マで続けて記述することもできます.     defs  nn  デファインストレージ.この行のある位置に、nn で指定     (ds)    される大きさの領域を確保します.確保された領域は、           ゼロでクリアーされています.     defm 'string'     (dm)    デファインメッセージ.string で指定される文字列のア           スキーコードを展開します.     end  nn  エンド.ソースプログラムの終わりを示す.これを発見           するとアセンブルを終了させます.オペランドは、その           プログラムの実行開始番地を指定します.これを省略し           た時は、プログラムの先頭が実行開始番地として解釈さ           れます.           end 命令は、省略しても構いません.テキストの最後ま           でアセンブルしますと、そこで自動的に終了します.      (本アセンブラーには、マクロ命令はありません.)   G エラーメッセージ     エラーメッセージは、アセンブルリストの中の、オブジェクトとソー    スとの間に表示されます.アセンブラーの出力するエラーメッセージは、    次に示す英文字 1 文字です.     F フォーマットエラー      ・ラベルが英字で始まっていない.      ・ラベルに禁止文字が使用されている、8 文字以内でない.     Q クウエションエラー      ・オペコードが 5 文字以上ある.      ・Z-80 のコードでない     0 オペランドエラー      ・必要なオペランドがない、不要なオペランドがある.     R リラティプエラー      ・相対分岐命令のオペランドの指定範囲が -126〜+129を越えている.     V ヴァリュウエラー      ・IM, RST, RES, SET, BIT 命令のオペランドの値が規格外である.     S ストリングエラー      ・’が足らない、余分にある.     U アンデファインエラー      ・参照ラベルが未定義である.     M マルチブルデファインエラー.      ・ラベルが多重定義されている.     L ラベルエラー.      ・equ 命令で定義すべきラベルがない. C system program 構成  本コンパイラーシステムは、システム全体を制御する「 C system 」、C プ ログラムを作成・編集する「 C editer 」、C プログラムをコンパイルしアセ ンブラソースプログラムを出力する「 C compiler 」、ならびにコンパイル出 力を編集・アセンブルする「 C editer & assembler 」より構成されています.  さらに、X1 本体のモニターは、「 C system 」の拡張コマンドとして取り込 まれています.  各プログラム動作時のプロンプトは、それぞれ以下のとおりとなっています.     C system ................. ">"     C editer ................. "$"     C editer & assembler      editer block ............ "#" assembler block ......... "]"  各プログラムは、すペて C system より起動し、起動されたプログラムは、 プログラム中のコマンドにより C system に戻るよう操作します.  以下にコンパイラーシステムの構成を図示します. +------------------------------------------------------+    |               拡張コマンド |    | C system  +------------+  により、X1 monitor |    |      | X1 monitor |  を直接呼び出すこ |    |      +------------+  とができる | +------------------------------------------------------+     ed↓↑!    c↓↑(auto)      ea↓↑! +----------+ +------------+ +-----------------------+    | C editer |  | C compiler | | C editer & assembler |    +----------+ +------------+ |  (editer block) |                    |    a↓↑! |                    |  (assembler block) | +-----------------------+ C system command (1)ed    内蔵の C editer を起動します.   C プログラムを人力することができるようになります.   C editer のコマンドについては、C editer command を参照してください. (2)ea    内蔵の C editer & assembler を起動します.    コンパイルオブジェクト(アセンブリソース)の編集、ならびにアセン   ブルができます.    C editer & assembler のコマンドについては、C editer & assembler   command を参照してください. (3)c[filename][ - ***** ] *: コンパイルオプション    コンパイルを実行します.    コンパイル中にエラーが見つかると、エラーのあった行番号とエラー内   容を、画面やプリンタ装置に出力します.    エラー内容によっては、その時点でコンパイルを打ち切ります.    file name は、コンパイルオブジェクトをテープに出力する時に指定し   ます.省略してもかまいません.file name に空白文字を含めることはで   きません.    コンパイルオプションは、"-"に続けて指定します.オプション指定は以   下のとおりです.    l: コンパイルオブジェクトを画面やプリンタ装置に出力しながらコン     パイルを行います.    c: C ソースプログラムをコメントとしてコンパイルオブジェクトの中     に出力します.    t: コンパイルオブジェクトをテープに出力します.    m####:      コンパイルオブジェクトの先頭番地を指定します.#### は4 桁の16     進数です.このオプション指定により、コンパイルオブジェクトの先     頭に「org ####h」の擬似命令が出力されます.    p: コンパイル中の画面出力をプリンタに切り換えます.   オプションの指定順番に制限はありません. (4)*%       (%: X1 monitor command .... S,L,D,M,P,T,F)    拡張コマンドです."*"に続けて X1 モニターコマンドを指定することに   より、X1 のモニターコマンドを実行します. C editer command (1)l [ln1[ln2]]        (list command)    ln1 からln2 までを画面にリスト表示します.ln2 を省略した時は、ln1 からテキストの最後までを表示します.ln1, ln2 とも省略した時は、テキ   ストの最初から最後までを表示します.    りスト表示の一時停止は、スペースキーを押す事により可能です.再度   スペースキーを押すとりスト表示を再開します. (2)p [ln1[ln2]]        (print command)    プリンター装置にリストを印刷します.範囲の指定等は、l コマンドと   同じです. (3)d ln1[ln2]]        (delete command)    ln1 から ln2 までの範囲のテキストを削瞼します.ln2 を省略した時は、 ln1 のみ削除します. (4)n             (new command)    メモリ内の現在のテキスト全体を削除します. (5)i [ln1]          (insert command)    ln1 以前にテキストを挿入します.    本コマンド投入後、画面上には、':' を表示してテキストの人力待ちと なります.一行人力する毎にリターンキーを押すことにより連続してテキ   ストの挿入が出来ます.    挿入をやめる時は、ブレークキーを押します.    なお、テキスト入力中は、':' 左側に入力しても無効となりますので注   意してください.    ln1 を省略したときは、現在のテキストの最後に、入力したテキストを   追加します. (6)r [ "filename" ]      (read command)    カセットテープから、指定された filename のテキストファイルをメモ リ内に読み込みます.filename が省略された時は、テープ上の最初のテキ ストファイルを読み込みます.    メモリ内に既にテキストが存在する時は、読み込んだテキストは、後に   追加されます.    読み込み途中でやめたい時は、ブレークキーを押して下さい. (7)w "filename" [ln1[ln2]]   (write command)    メモリ内のテキスト中の ln1 から ln2 までの範囲を指定された   filename をつけてカセットテープに書き込みます.   ln2 を省略した時は、ln1 からテキストの最後までを書き込みます.   ln1,ln2 とも省略した時は、テキスト全体を書き込みます.   書き込み途中でやめたい時は、ブレークキーを押して下さい.    filename は省略出釆ません. (8)s "strings" [ln1[ln2]] (search command)    メモリ内のテキスト中の ln1 から ln2 までの範囲内から、指定された   strings を含むテキスト行を画面に表示します.    ln2 を省略した時は、ln1 からテキストの最後までが検索対象となりま   す.ln1,ln2 とも省略した時は、テキスト全体が検索対象となります. (9)m ln1 ln2 [ln3]          (move command)    ln1 から ln2 までの範囲のテキストを、ln3 以前に移動します.    ln3 を省略した時は、テキストの最後に移動します.    ln1,ln2,ln3 の指定可能範囲は、次のとおりです.       イ.ln1 =< ln2, ln3 < ln1       ロ.ln1 =< ln2, ln3 > ln2 +1 (10)c ln1 ln2 [ln3]         (copy command)    ln1 から ln2 までの範囲のテキストを、ln3 以前に複写します.    ln3 を省略した時は、テキストの最後に複写します.    ln1,ln2,ln3 の指定可能範囲は、次のとおりです.       イ.ln1 =< ln2, ln3 =< ln1       ロ.ln1 =< ln2, ln3 > ln2 (11)f    ファンクションキーの現在の定義状態を表示します.    表示された内容は、screen edit が可能です.    画面制御文字は、esc を押してから ctrl+M のように入力して下さい. (12)!    C system に戻ります.    入力したテキストはメモリ内に保存されたままですので、C system から 再度 editer を起動すれば続けてテキストの編集が可能です.            」 (注)  ○ 本 editer は全ての場合において screen edit が可能です.  ○ l command や s command にて画面に表示された内容は、修正したい位置   にカーソルを移動して、必要な修正の後リターンキーを押すことにより容   易に修正出来ます.  ○ なお、i command によるテキスト入力時に、画面に表示された人力済内   容の修正はできません.この時は、新たな人力行としてテキストに格納さ   れます. C editer & assembler command   editer block (1)l [ln1[ln2]]        (list command)    ln1 からln2 までを画面にリスト表示します.ln2 を省略した時は、ln1 からテキストの最後までを表示します.ln1, ln2 とも省略した時は、テキ   ストの最初から最後までを表示します.    りスト表示の一時停止は、スペースキーを押す事により可能です.再度   スペースキーを押すとりスト表示を再開します. (2)p [ln1[ln2]]        (print command)    プリンター装置にリストを印刷します.範囲の指定等は、l コマンドと   同じです. (3)d ln1[ln2]]        (delete command)    ln1 から ln2 までの範囲のテキストを削瞼します.ln2 を省略した時は、 ln1 のみ削除します. (4)n             (new command)    メモリ内の現在のテキスト全体を削除します. (5)i [ln1]          (insert command)    ln1 以前にテキストを挿入します.    本コマンド投入後、テキストの人力待ちとなります.一行人力する毎に   リターンキーを押すことにより連続してテキストの挿入が出来ます.    挿入をやめる時は、ブレークキーを押します.    ln1 を省略したときは、現在のテキストの最後に、入力したテキストを   追加します. (6)r [ "filename" ]      (read command)    カセットテープから、指定された filename のテキストファイルをメモ リ内に読み込みます.filename が省略された時は、テープ上の最初のテキ ストファイルを読み込みます.    メモリ内に既にテキストが存在する時は、読み込んだテキストは、後に   追加されます.    読み込み途中でやめたい時は、ブレークキーを押して下さい. (7)w "filename" [ln1[ln2]]   (write command)    メモリ内のテキスト中の ln1 から ln2 までの範囲を指定された   filename をつけてカセットテープに書き込みます.   ln2 を省略した時は、ln1 からテキストの最後までを書き込みます.   ln1,ln2 とも省略した時は、テキスト全体を書き込みます.   書き込み途中でやめたい時は、ブレークキーを押して下さい.    filename は省略出釆ません. (8)s "strings" [ln1[ln2]] (search command)    メモリ内のテキスト中の ln1 から ln2 までの範囲内から、指定された   strings を含むテキスト行を画面に表示します.    ln2 を省略した時は、ln1 からテキストの最後までが検索対象となりま   す.ln1,ln2 とも省略した時は、テキスト全体が検索対象となります. (9)m ln1 ln2 [ln3]          (move command)    ln1 から ln2 までの範囲のテキストを、ln3 以前に移動します.    ln3 を省略した時は、テキストの最後に移動します.    ln1,ln2,ln3 の指定可能範囲は、次のとおりです.       イ.ln1 =< ln2, ln3 < ln1       ロ.ln1 =< ln2, ln3 > ln2 +1 (10)c ln1 ln2 [ln3]         (copy command)    ln1 から ln2 までの範囲のテキストを、ln3 以前に複写します.    ln3 を省略した時は、テキストの最後に複写します.    ln1,ln2,ln3 の指定可能範囲は、次のとおりです.       イ.ln1 =< ln2, ln3 =< ln1       ロ.ln1 =< ln2, ln3 > ln2 (11)a    assembler block への切り換えをおこないます. (12)!    C system に戻ります.    入力したテキストは削除されますので、保存が必要な場合は w コマンド   によりテープに書き込んでおいてください. (注)  ○ 本 editer は全ての場合において、screen edit が可能です.  ○ l command や s command にて画面に表示された内容は、修正したい位置   にカーソルを移動して、必要な修正の後リターンキーを押すことにより容   易に修正出来ます.  ○ なお、i command によるテキスト入力時に、画面に表示された人力済内   容の修正はできません.この時は、新たな入力行としてテキストに格納さ   れます.  ○ 各コマンドにおける行指定(ln1,ln2ln3)は、テキスト上のラベル名が   使用できます.   assembler block (1)1 [ln1[ln2]]       (pass 1)    ln1 から ln2 の範囲のテキストを対象に、ラベルの登録処理を行いま   す.ln2 が省略された時は、ln1 からテキストの最後までが処理対象とな   ります.ln1,ln2 とも省略したときは、テキスト全体が対象となります. (2)2 [ln1[ln2]]       (pass 2)    アセンブルの結果を画面に表示します.行番号指定は、pass1 と同じで   す. (3)3 [ln1[ln2]]       (pass 3)    アセンブルの結果をプリンタ装置に表示します.行番号指定は、pass1   と同じです. (4)4 [ln1[ln2]]       (pass 4)    アセンブルオブジェクトをメモリ上に生成します.    エラーが発見されると、その時点で処理をうちきります.   行指定(ln1,ln2,ln3)は、editer block と同様にテキスト上のラベル名   が使用できます. (5)s    pass1 で登録したラベルをアルファベット順に画面に表示します. (6)p    pass1 で登録したラベルをアルファベット順にプリンタ装置に出力しま   す. (7)r [arg1 arg2 ... argn ]    pass4 で生成したアセンブラオブジェクトを実行します.    arg は、C の main 関数へ渡す引数文字列です.    アセンブラオブジェクトの実行開始番地が、メモリ上のテキストや   editer & assembler の格納番地と重複するときは、      ・text destroy ok? ........ テキスト領域と重複する時      ・system destroy ok? ...... edi & ase 本体と重複する時   を出力しますので、破壊しては困る場合は、ブレークキーを押してくださ   い.その他のキーを押すと実行します. (8)e    pass2 (or pass3) において、アセンブルエラーのあった行のみ出力しま   す.本コマンドは、トグルスイッチとなっていますので、再度のコマンド   投入によりエラー以外の行も出力するようになります. (9)t1〜t4    カセットテープ上のアセンブリーソースファイルを対象に、pass1〜 pass4 の処理を実行します.    C compile object や editer の w コマンドで作成したテープをカセッ   トにセットしてからコマンドを投入します.テープからテキストを読み込   みながら処理します.    editer & assembler のワークエリアが不足する時に、テープから読み込   みながら処理することにより、相当大きなプログラムもアセンブルするこ   とが可能となります. (10)l    複数のソースファイルをリンクします.    本アセンブラは、ソースでリンクするものであり、通常小さなソースフ   ァイルは、アセンブルに先立って editer の r コマンドによりメモリ上で   一つにしておけばよいのですが、メモリに格納しきれない大きなソースは   次のような手順で処理します.    ] l     ... l コマンド投入    ]      ... カセットにファイル名 'tape-1' のテープをセット    ] t1     ... t1 コマンド投入    assembling tape-1    ]      ... カセットにファイル名 'tape-2' のテープをセット    ] t1     ... t1 コマンド投入    assembling tape-2    ]      ... カセットにファイル名 'tape-1' のテープをセット    ] t4     ... t4 コマンド投入    assembling tape-1    ]      ... カセットにファイル名 'tape-2' のテープをセット    ] t4     ... t4 コマンド投入    assembling tape-2    ]              (]: アセンブラプロンプト)    pass2,pass3 も同様な手順で処理します.    リンクするファイルの内、どれか一つはメモリ上のテキストファイルを   選択することが可能です(ワークエリアの許す限り). (11)b    pass4 で作成したオブジェクトをカセットテープに格納します.   本コマンド投人後、ファイル名を聞いてきますので適当なファイル名を人   力してください. (12)!    editer block への切り換えをおこないます.    pass1 で登録したラベルは削除されます. アセンブラ関数の作成に閑して  インラインの機能や、editer & assembler にて、アセンブラ言語による関数 を作成する場合に、知っておくべき事柄について説明します. (1)関数名    C プログラム内の各関数名は、コンパイルオブジェクト上では、そのま   まの名前がラベルとして出力されており、関数呼び出しは、単純に当該ラ   ベルを人口とするサブルーチンヘのコールとなっています.このため、ア   センブラで作成する関数の人口ラベル名は、C プログラムの中で、呼び出   す関数名をそのままつければよいこととなります. (2)引数の受け渡し    C プログラムの関数呼び出しは、引数を右側から左に向かって評価し、   評価結果は、型にかかわらずすべて 2 バイトの大きさで、スタックにプッ   シュされた後サブルーチンコールされます.    アセンブラ関数に飛び込んできた時のスタックトップには、リターンア   ドレスが積まれており、さらに、その下には左側の引数が積まれているこ   ととなります。    アセンブラ関数では、リターンアドレスを適当に保存すれば、後は pop   命令により順次、左側からの引数を受け取ることができます.    この時、注意しなければいけないのは、アセンブラ関数から戻る時、ス   タックの深さを変えてはいけないことです.引数のプッシュによるスタッ   クの消費は、呼び出した関数側でもとに戻されるからです. (3)関数からの戻り値の受け漉し    コンパイラは、関数から戻す値は、すべての場合において hl レジスタ   により実現させています.呼び出した関数側においても、hl レジスタに戻   り値があるものとして、式のオブジェクト展開がされます.    このため、アセンブラ関数から C プログラムに値を渡すためには、hl   レジスタに処理結果を格納すればよいこととなります. (4)レジスタ保護    式の評価の途中でアセンブラ関数が呼ばれるような時でも、呼び出し直   前の評価値はスタックに退避されており演算処理にかかわるレジスタ(hl,   de,a) の保護は、特に考慮する必要はありません.    ただ、bc レジスタは、実行中の関数のスタックフレームのポインタとし   て使用されていますので、これについては、アセンブラ関数の中で保護し   なければなりません.    関数のスタックフレームや、ローカル変数へのアクセス等、コンパイラ   の出力するオブジェクト展開についは、次項に示しておきましたので参考   にしてください. 関数の stack frame の構成と変数へのアクセス  本コンパイラーで生成する関数オブジェクトの、スタックの構成やローカル 変数へのアクセスについて、次に図をもちいて示します. (1)stack frame の基本構成 | | +-----------+ sp -->| | func(arg1,arg2) +- local 3 -+ int arg1; | | char arg2; +-----------+ { int local1; | local2[0] | char local2[3]; +-----------+ .................... | local2[1] | .................... +-----------+ { int local3; | local2[2] | .............. +-----------+ .............. | | } +- local 1 -+ .................... | | } +-----------+ bc -->| [ bc ] | func: push bc    ; 関数入口処理 +- frame -+ ld hl,0 | pointer | add hl,sp +-----------+ ld b,h | | ld c,l +- return -+ ld hl,(@10xx) | address | add hl,sp +-----------+ ld sp,hl | | ............ +- arg 1 -+ ............ | | ............ +-----------+ ld h,b   ; 関数出口処理 | arg 2 | ld l,c +- -+ ld sp,hl | [ 00 ] | pop bc +-----------+ ret | | @10xx: defb -7  ; ローカル変数の総バイト数                         (負符号付)   関数の入口処理では、その関数で使用するローカル変数の領域をスタック  に確保します.そして、出口処理では、確保した領域を開放してからその関  数を呼び出した関数ヘリターンします.関数内のブロックの先頭で宣言され  る変数の領域についても、当該ブロックの処理の実行の如何を問わず、人口  処理でまとめて確保します.   呼び出し側関数の bc レジスタは、入口処理の先頭でスタックに退避し、  その退避したアドレスを bc レジスタに格納します.これにより、ローカル  変数は、bc レジスタのアドレスからのオフセットを用いることによりアクセ  スすることができます.このため、bc レジスタは、フレームポインタとして  常に実行中の関数のスタックフレームを管理していることになります. (2)ローカル変数、引数へのアクセス    それでは、bc レジスタのフレームポインターによりローカル変数や引数  にアクセスするところをしめします. @ local1 へのアクセス A arg2 へのアクセス ld hl,-002 ld hl,006 add hl,bc add hl,bc ld a,(hl) ld l,(hl) inc hl ld h,0 ld l,(hl) ld h,a B local2 の要素2へのアクセス ld hl,-005 add hl,bc inc hl inc hl ld l,(hl) ld h,0 (3)関数呼び出し、戻り時の処理    関数を呼び出す時は、右側の引数から左に向かって順にスタックにプッ   シュした後、目的の関数を単にサブルーチンコールするだけです.呼び出   された関数からリターンしてきた後、引数をプッシュした分だけスタック   を開放します.引数は、型にかかわらず2バイトの大きさでプッシュしてい   ます. ............... ld hl,(arg2) func1() push hl { ld hl,(arg1) ......... push hl func2(arg1,arg2); call func2 .......... pop af pop af } ............... memory map (1)C-system 動作時 0000 +--------------+ | X1 cios | C-editer で作成したテキスト 1000 +--------------+ は、graphic memory に格納さ | X1 monitor | れます.(約 48kb のテキスト 14A0 +--------------+    領域となります)   | C-system | +--------------+ 2000 | C-editer | +--------------+ | C-compiler | graphic memory 4000 | | 4000 +--------------+ | | | | 6800 +--------------+ | C-source | | editer & | | text buffer | | assembler | | | 87FF +--------------+ | | | | | | | | | | | | | | | | | | | | | | FF00 +--------------+ | | | stack | | | FFFF +--------------+ FFFF +--------------+ (2)C-editer 動作時 0000 +--------------+ | X1 cios | 1000 +--------------+ | X1 monitor | 14A0 +--------------+     main memory の 4000 〜 FEFFと、 | C-system | graphic memory の 4000 〜 FEFFの +--------------+ 内容が交換されます. 2000 | C-editer | +--------------+ | C-compiler | graphic memory   4000 +--------------+ 4000 +--------------+ | | | C-compiler | | C-source | 6800 +--------------+ | text buffer | | editer & | | | | assembler | | | 87FF +--------------+ | | | | | |  ⇔ | | | | (交換)| | | | | | | | | | FF00 +--------------+ | | | stack | | | FFFF +--------------+ FFFF +--------------+ (3)C-compiler 動作時    C-system 動作時に同じです.C-compiler は、graphic memory から C   ソーステキストを読み込みながらコンパイルを行います.コンパイルオ   ブジェクト(アセンブリソース)は、main memory の 8800 〜 FEFF の領   域に出力します. (4)C-editer & assembler 動作時 0000 +--------------+ | X1 cios | 1000 +--------------+ | X1 monitor | 14A0 +--------------+    | C-system | +--------------+ | C-editer | 2000 +--------------+ | editer & | | assembler | graphic memory   4000 +--------------+ 4000 +--------------+ | assembly- | | C-source | | source | | text buffer | | text buffer | | | | | | | | | | | | assembly- | 9800 +--------------+ |object buffer |  | C-editer | | | | C-compiler | | assembly- | +--------------+ | label buffer | | editer & | FF00 +--------------+ | assembler | | stack | | | FFFF +--------------+ FFFF +--------------+   step1 main memory の 2000 〜 87FF の内容を、graphic memory の      9800 〜 FFFF に退避します. step2 main memory の 6800 〜 87FF にあるediter & assembler を      2000 以降に移動します. step3 main memory の 87FF 以降に格納されていたコンパイルオブジェク      ト(アセンブリソース)を 4000 以降に移動します.      移動したソースを含め、4000 〜 FEFF の領域をアセンブリーオブ      ジェクトやラベルの格納領域として使用します.   step1 において、C-editer で作成した C-source text が 9800 番地を越   えて格納されていた場合には、9800 以降の内容は、C-editer, C-compiler の退避により削除されます.このような場合には、editer & assembler の   起動時に text destroy ? の確認を表示します.y 以外のキー入力により   editer & assembler の起動は中止できます. システム固有のこと  本コンパイラシステムの固有の諸点について、システムの改造等を試みる場 合の参考事項を説明したいとおもいます. (1)アセンブラシステムの分離    システムに組み込んであるアセンブラシステムは、それ単独で充分使用   に耐えるものであります.事実このコンパイラシステム自体も、これによ   って作成しています.    ここでは、これの分離方法を説明します.    アセンブラシステムは、0x2000 番地から 0x3fff 番地に格納されて実行   するものですが、C-system 動作時は、0x6800 〜 0x87ff の領域に存在し   ています.C-system より "*g1000" と打ち込んで X1 モニタに飛び、後は   モニタのコマンドにより、アセンブラシステムを 0x2000 番地以降に転送   し、0x012a 〜 0x012c の jump 命令をC3、00、20 に変更したうえで、モ   ニタと合わせて一括テープにセーブすれば、IPL 起動のアセンブラシステ   ムを作ることができます. (2)C プログラムのオブジェクトを単独で動かす    コンパイル・アセンブルの過程を経て作成された C のオブジェクトは、   現在 C-system の存在なしでは、実行できません.この理由は、単にラン   タイムが C-system の中に組み込んであるがためです.コンパイルオブジ   ェクトをアセンブラシステムのエディタでリスト表示しますと、オブジェ   クトの先頭にランタイムの人口ラベルが eque によりアドレス定義されて   いるのがわかるとおもいます.    説明書の最後に、システムで組み込んでいるランタイムのアセンブラリ   ストを付けていますので、これ、又は、これ相当のものを別アドレスにア   センブルして equ の定義を変更するか、定義を削除した上でオブジェクト   とランタイムをまとめてアセンブルすれば、X1 モニタのもとで、単独で実   行させることが可能となります.ただし、main 関数への引数渡しは、でき   ませんので、プログラムの中で必要な人力処理をコーディングしておいて   ください.さらに、実行開始前の sp の設定についても考慮しておくこと   を忘れないでください. (3)システムの他機種への移植の可能性について    メモリマップの説明を見て頂くとわかりますように、メインメモリの他、   グラフィックメモリもフルに活用してシステムを実現していますので一見   不可能に見えますが、これは、テープシステムの操作性を極力向上させる   ために、各プログラムが起動する直前にメモリ配置を動かしているだけで、   コンパイラや、アセンブラの本質の部分には関係ありません.    とはいえ、これは X1 のもつカセットシステムの高信頼性と、メモリオ   ール RAM の特質あってのことですから、他機種へのテープシステムによる   移植は困難といえるでしょう.    ディスクシステムともなれば、それなりの DOS が完備されていれば、   各プログラム毎に若干の DOS インタフェースをコーディングすればよく、   可能性はあることでしょう.(私自身、いずれはディスク版を作成したい   と思っています.) 最後にあたって  今回のコンパイラ作成は、まず C 言語とはどんなものかというところから始 めなければなりませんでした.私自身は、C 言語を実際に動かしたこともなく、 周囲に C 言語に精通したものもいず、市販の図書からの習得でした.  言語は動かしてみるのが習得の早道であるわけですが、文法書を読めば大体の ことは掴めるものなのですが、C 言語は、きちんとした文法があるわけでなく、 余分な苦労をしたと思っています.  事実、エラー処理においては、エラーを出力すべきなのか、適当にコンパイラ が処理してもよいのか悩むことが多々ありました.このため、今回の説明では、 意図的にエラーメッセージについては説明を省略しました.一応、それなりのエ ラーメッセージは出力するようにしてあります.  コンパイラの細部設計においては、型の管理が特に難しいように感じました. それと、やはり C の持つ豊富な演算子による式処理は、コンパイラの大部分を 占めることとなりました.もう一つ、コンパイラの構文解析を複雑にしている ものとして、後に続く語句によって処理がかわることです.たとえば、単項式 の処理で,"(" を読み込んでも、それが1次式の左括弧なのか、キャストの左括 弧なのか、"(" を読み込んだ時点では決定できません."++" や "--" 演算子が 左辺値の後に続くことも同様です.また、式として定義されているものの論理演 算や条件式のコンパイルは、if文の処理と同様のオブジェクト展開が要求されま す.basic は、インタブリタ言語であるためでしょうか、この辺はコンパイラを 作るにあたっては楽です.必ず文頭にキーワードが存在し、それによって処理が 決定されるからです.  最適化については、C 言語自体が最適化を考慮したコーディングができるわけ で、無理に行う必要はないのかもしれませんが、定数との加減算をインクリメン ト・デクリメントに、2 のペき乗の定数との乗算をシフト命令に置き換えていま す.  関数の入口出口処理は、引数や局所変数の有無に応じて個々に最適化すべき余 地があるわけですが、1 パスのコンパイラであること、複文の先頭での変数宣言 によるスタックの領域確保を簡単にしたため、ワンパターンなオブジェクト展開 となってしまいました.その他にも、不要なオブジェクトが展開されている部分 があります.  今後、コンパイラを作って見ようと思われている方に参考になればと、とりと めもない事を書いて見ましたが、本コンパイラは、なにぶん仕事で忙しい中、日 曜大工的に作ったものですので、バグが多分にひそんでいるのではないかと心配 しています.  最後に、テープ4 に納めてあるデモプログラムについて一言. I/O 11月号掲載の、秦和夫氏の "MZ-2500用メモリダンプ&エディタ" の画面表 示スタイルを真似たメモリダンププログラムを C でコーディングしてみました. コンパイルオプション "-tmc000" でコンパイル・アセンブルしますと、システ ムを破壊することなく実行できます.プログラムは、基本的な機能の部分だけで すので、ツールとして使用するには貧弱ですが、C 言語の応用の一例として、ふ さわしいと思いましたので作ってみました. 参考文献 @ B.W.カーニハン/D.M.リッチー 著   プログラミング言語C、共立出版 A クロビス.L.トンド/スコット.E.ギンペル 著   Cアンサー・ブック、啓学出版 B 西田親生/五月女健治 著   C言語プログラミング入門、啓学出版 C J.E.へンドリックス 著   Small−Cハンドブック、工学社 D ROBERT J.TRAISTER 著   BASIC to C、アスキー出版局 E マイコンピュータ 1983.No.10 "入門特集 C言語の研究"   CQ出版社 F 伊東正安/石川 正 著   インタフエース 1980.No.43 172ページ   "Z−80/8080アセンブラ"、CQ出版社 G インタフエース 1982.No.62   "特集 システム記述言語Cとその応用"、CQ出版社 H インタフェーズ 1984.No.80   "特集 CP/M−68K制作とコンパイラ"、CQ出版社 I インタフエース 1984.No.85   "特集 Cのすペて"、CQ出版社 J インタフエース 1984.No.86   "特集 続・Cのすべて"、CQ出版社 K 河西朝雄 著:C標準ライブラリ関数、ナツメ社 L 中西正和/大野義夫 著:やさしいコンパイラの作り方、共立出版 M 清水保弘 著:]1マシン語活用百科、産業報知センター