1 \input texinfo @c -*-texinfo-*-
4 @settitle YACASL2 - Linux上のCASL2処理系
8 Copyright @copyright{} 2010 j8takagi
15 @c Output the table of contents at the beginning.
22 @cindex chapter, first
24 YACASL2は、Linux上で動作するオープンソースのCASL II処理系です。CASL IIは情報処理試験で用いられるアセンブラ言語で、次の資料により仕様が公開されています。
27 @uref{http://www.jitec.ipa.go.jp/1_00topic/topic_20081027_hani_yougo.pdf, 試験で使用する情報処理用語・プログラム言語など(2008年10月版)}[PDFファイル]
31 YACASL2は、CASL IIアセンブラ言語で記述されたファイルをアセンブルし、仮想マシンCOMET II上で実行します。アセンブルと実行は、連続で行うことも別々に行うことも可能です。
32 YACASL2の動作はCASL IIの仕様に準拠しているため、情報処理試験の問題をはじめ各種参考書やサイトに記載されたCASL IIのプログラムをそのままアセンブルして実行できます。また、本パッケージ中にCASL IIのサンプルプログラムが多数収録されています。
34 YACASL2は、「ふつうの処理系」として動作します。ほかの多くのCASL IIエミュレーターと違い、デバッガーとして動作したり、コンピューター内部の模式図を表示したりすることはありません。そのかわり、YACASL2は、次のような動作内容をすべてテキストで出力します。
51 出力された動作内容は、GNU/Linuxのさまざまなツール、たとえば@command{cat}、@command{less}、@command{grep}、@command{wc}などを使って解析できます。
54 YACASL2は、Linux上で動作します。現在動作を確認しているのは、次のディストリビューションです。
59 Ubuntu Linux 9.04 / 8.04
65 インストール時に、@command{tar}、@command{gcc}、@command{make}が必要です。
67 @chapter YACASL2のインストール
69 YACASL2をインストールするには、Linux上で次の作業をします。
74 @file{yacasl2.tar.gz}のダウンロード
77 @file{yacasl2.tar.gz}の検証
80 @file{yacasl2.tar.gz}の展開
83 @command{casl2}、@command{comet2}、@command{dumpword}のビルド
95 以下の操作は、端末を開きコマンドを実行します。
97 @section @file{yacasl2.tar.gz}のダウンロード
102 $ @b{wget somewhere/yacasl2.tar.gz}
103 $ @b{wget somewhere/yacasl2.tar.gz.md5sum}
106 @section @file{yacasl2.tar.gz}の検証
110 ダウンロードが完了したら、@command{md5sum}と@command{diff}で正しくファイルがダウンロードができているかを検証します。
113 $ @b{md5sum yacasl2.tar.gz | diff -s yacasl2.tar.gz.md5sum -}
114 Files yacasl2.tar.gz.md5sum and - are identical
117 @section @file{yacasl2.tar.gz}の展開
119 @file{yacasl2.tar.gz}をダウンロードしたら、次のコマンドで展開します。
122 $ @b{tar xvzf yacasl2.tar.gz}
125 @section @command{casl2}、@command{comet2}、@command{dumpword}のビルド
127 展開したら、次のコマンドで@command{casl2}、@command{comet2}、@command{dumpword}をビルドします。
133 make[1]: Entering directory ‘/home/kazubito/yacasl2/src’
134 gcc -c -g -Wall -I ../include casl2.c
135 gcc -c -g -Wall -I ../include word.c
136 gcc -c -g -Wall -I ../include hash.c
137 gcc -c -g -Wall -I ../include cerr.c
138 gcc -c -g -Wall -I ../include struct.c
139 gcc -c -g -Wall -I ../include cmd.c
140 gcc -c -g -Wall -I ../include assemble.c
141 gcc -c -g -Wall -I ../include token.c
142 gcc -c -g -Wall -I ../include label.c
143 gcc -c -g -Wall -I ../include macro.c
144 gcc -c -g -Wall -I ../include exec.c
145 gcc -c -g -Wall -I ../include dump.c
146 gcc -g -Wall -I ../include -o ../casl2 casl2.o word.o hash.o cerr.o st
147 ruct.o cmd.o assemble.o token.o label.o macro.o exec.o dump.o
148 gcc -c -g -Wall -I ../include comet2.c
149 gcc -g -Wall -I ../include -o ../comet2 comet2.o word.o hash.o cerr.o
150 struct.ocmd.o exec.o dump.o
151 gcc -c -g -Wall -I ../include dumpword.c
152 gcc -g -Wall -I ../include -o ../dumpword dumpword.o word.o cerr.o
153 make[1]: Leaving directory ‘/home/kazubito/yacasl2/src’
156 @section @command{casl2}の実行テスト
158 ビルドしたら、次のコマンドが正常に実行できるかを確認します。
159 正常に実行された場合は、「Hello, World!」と表示されます。
162 $ @b{./casl2 as/hello.casl}
168 次のコマンドを実行すると、正常にビルドできているかどうかを詳細にテストできます。
174 @section 環境設定@var{PATH}の設定
176 環境変数@var{PATH}にYACASL2のディレクトリーを追加すると、どのディレクトリーでも@command{casl2}、@command{comet2}、@command{dumpword}を実行できます。
178 環境変数の設定方法は使っているシェルによって異なります。シェルは、次のコマンドで確認できます。現在もっとも多く使われているのは、BASHでしょう。
184 シェルがBashの場合、次のコマンドを実行すると環境変数@var{PATH}にYACASL2のディレクトリーが追加されます。
186 $ @b{PATH=$PATH:~/yacasl2 && export PATH}
189 シェルの初期設定ファイルに上記のコマンドを追加すれば、今後ログインした後は自動的にどのディレクトリーでも @command{casl2}、@command{comet2}、@command{dumpword}を実行できるようになります。BASHの場合はホームディレクトリーにある@file{.bashrc}が初期設定ファイルのため、コマンドは次のようになります。
191 $ @b{echo ’PATH=$PATH:~/yacasl2 && export PATH’ >>~/.bashrc}
194 @chapter YACASL2 の使い方
196 YACASL2 は、テキストファイルに記述されたCASLプログラムを処理します。以下の例で用いられるCASLプログラムのファイルは、テキストエディタなどで作成してください。また、インストールしたディレクトリーの中にある@file{as}ディレクトリーからコピーして作成することもできます。
198 @section 実行結果の出力だけを表示
200 インストール時にコマンド実行の確認に使った@file{hello.casl}は、次のような内容です。CASL IIのマクロ命令OUTは、文字列を出力します。
206 OBUF DC ’Hello, World!’
211 次のコマンドを実行すると、CASL II のアセンブルと仮想マシン COMET II 上での実行が連続で行われ、文字列が出力されます。
213 $ @b{casl2 hello.casl}
217 @file{addl.casl}は、3と1の和を求めます。
231 このプログラムには出力命令がないため、オプションなしで実行した場合には結果が出力されません。
234 $ @b{casl2 addl.casl}
238 実行内容を確認するには、後述のようにCPU 内にあるレジスターやメモリーの内容を表示するか、結果を出力するための処理を追加する必要があります。
240 @file{sum_10.casl}は、1から10までの整数の和を求めます。
243 $ @b{cat sum_10.casl}
245 ;;; 出力 GR0: 1から10までの整数をすべて加算した値
249 LD GR1,FST ; GR1に初項を転送
250 LOOP ADDL GR0,GR1 ; ループ先頭
251 ADDL GR1,STEP ; GR1 <- GR1 + 公差
252 CPL GR1,LST ; GR1が末項より大きい場合は終了
263 このプログラムも、オプションなしで実行した場合には結果が出力されません。
265 $ @b{casl2 sum_10.casl}
270 casl2の処理途中で行われるアセンブルの結果を表示するには、オプション@option{-a}を指定します。また、ラベルとアドレスの対応表を表示するには、オプション@option{-l}を指定します。
272 次のコマンドでは、@file{hello.casl}のラベルとアドレスの対応表と、アセンブル結果と、実行結果が表示されます。OUTはアセンブラ命令で複数の機械語命令で構成されているため、命令行1行に対して、複数行のコードが生成されます。
275 $ @b{casl2 -a -l hello.casl}
277 Assemble hello.casl (0)
284 Assemble hello.casl (1)
285 hello.casl: 1:MAIN START
286 hello.casl: 2: OUT OBUF,LEN
309 hello.casl: 4:OBUF DC 'Hello, World!'
323 hello.casl: 5:LEN DC 13
329 @file{addl.casl}のラベルとアドレスの対応表と、アセンブル結果は、次のようになります。
332 $ @b{casl2 -a -l addl.casl}
334 Assemble addl.casl (0)
341 Assemble addl.casl (1)
342 addl.casl: 1:;;; ADDL r,adr
343 addl.casl: 2:MAIN START
344 addl.casl: 3: LD GR1,A
347 addl.casl: 4: ADDL GR1,B
359 なお、オプション@option{-A}を指定すると、アセンブル結果だけが表示され、仮想マシンCOMET II での実行は行われません。
361 @section 実行時のレジスターとメモリーを表示
362 YACASL2では実行中のCPUのレジスターとメモリーの内容をそれぞれ、@option{-t}と@option{-d}を指定することで表示できます。
364 また、@option{-M}で、仮想マシンCOMET II のメモリー容量を語(16 ビット)単位で指定できます。小さいプログラムを実行するときは、メモリー容量を小さくすれば結果が見やすくなります。
366 @file{addl.casl}に必要なメモリー容量は8語のため、次のようにCPUのレジスターとメモリーの内容を表示できます。
369 $ @b{casl2 -t -d -M8 addl.casl | less}
371 Assemble addl.casl (0)
373 Assemble addl.casl (1)
375 Executing machine codes
377 #0000: GR0: 0 = #0000 = 0000000000000000
378 #0000: GR1: 0 = #0000 = 0000000000000000
379 #0000: GR2: 0 = #0000 = 0000000000000000
380 #0000: GR3: 0 = #0000 = 0000000000000000
381 #0000: GR4: 0 = #0000 = 0000000000000000
382 #0000: GR5: 0 = #0000 = 0000000000000000
383 #0000: GR6: 0 = #0000 = 0000000000000000
384 #0000: GR7: 0 = #0000 = 0000000000000000
385 #0000: SP: 8 = #0008 = 0000000000001000
386 #0000: PR: 0 = #0000 = 0000000000000000
387 #0000: FR (OF SF ZF): 000
389 #0000: adr : 0000 0001 0002 0003 0004 0005 0006 0007
390 #0000: 0000: 1010 0005 2210 0006 8100 0003 0001 0000
392 #0002: GR0: 0 = #0000 = 0000000000000000
393 #0002: GR1: 3 = #0003 = 0000000000000011
394 #0002: GR2: 0 = #0000 = 0000000000000000
395 #0002: GR3: 0 = #0000 = 0000000000000000
396 #0002: GR4: 0 = #0000 = 0000000000000000
397 #0002: GR5: 0 = #0000 = 0000000000000000
398 #0002: GR6: 0 = #0000 = 0000000000000000
399 #0002: GR7: 0 = #0000 = 0000000000000000
400 #0002: SP: 8 = #0008 = 0000000000001000
401 #0002: PR: 2 = #0002 = 0000000000000010
402 #0002: FR (OF SF ZF): 000
404 #0002: adr : 0000 0001 0002 0003 0004 0005 0006 0007
405 #0002: 0000: 1010 0005 2210 0006 8100 0003 0001 0000
407 #0004: GR0: 0 = #0000 = 0000000000000000
408 #0004: GR1: 4 = #0004 = 0000000000000100
409 #0004: GR2: 0 = #0000 = 0000000000000000
410 #0004: GR3: 0 = #0000 = 0000000000000000
411 #0004: GR4: 0 = #0000 = 0000000000000000
412 #0004: GR5: 0 = #0000 = 0000000000000000
413 #0004: GR6: 0 = #0000 = 0000000000000000
414 #0004: GR7: 0 = #0000 = 0000000000000000
415 #0004: SP: 8 = #0008 = 0000000000001000
416 #0004: PR: 4 = #0004 = 0000000000000100
417 #0004: FR (OF SF ZF): 000
419 #0004: adr : 0000 0001 0002 0003 0004 0005 0006 0007
420 #0004: 0000: 1010 0005 2210 0006 8100 0003 0001 0000
423 @subsection 特定のレジスターを表示
425 @file{addl.casl}のレジスターやメモリーの中で、実行中に値が変化しているのはGR1だけです。こうした場合は、@command{grep}を使って表示される内容を絞り込むことで動作を検証しやすくなります。
428 $ @b{casl2 -t addl.casl | grep 'GR1:'}
429 #0000: GR1: 0 = #0000 = 0000000000000000
430 #0002: GR1: 3 = #0003 = 0000000000000011
431 #0004: GR1: 4 = #0004 = 0000000000000100
434 ここで、先に実行した@file{addl.casl}のアセンブル結果をもう一度見てください。
435 次の表のように、PRとGR1、命令行が対応していることがわかります。
437 @multitable @columnfractions .3 .3 .4
438 @item PR @tab GR1 @tab 命令行
446 @tab @code{ADDL GR1,B}
449 @subsection プログラム終了時の値を表示
451 @command{grep}と@command{tail}を組み合わせれば、プログラム終了時の値を表示できます。
454 $ @b{casl2 -t addl.casl | grep 'GR1:' | tail -1}
455 #0004: GR1: 4 = #0004 = 0000000000000100
459 $ @b{casl2 -t sum_10.casl | grep 'GR0:' | tail -1}
460 #0010: GR0: 55 = #0037 = 0000000000110111 = '7'
463 @subsection プログラムのステップ数を表示
465 @command{grep}と@command{wc}を組み合わせれば、プログラムのステップ数を表示できます。
468 $ @b{casl2 -t hello.casl | grep 'GR1:' | wc -l}
473 $ @b{casl2 -t addl.casl | grep 'GR1:' | wc -l}
477 @file{sum_10.casl}はプログラム内にループがあるため、ステップ数が大きくなります。
480 $ @b{casl2 -t sum_10.casl | grep 'GR0:' | wc -l}
484 @section アセンブルと実行を別に行う