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.o cmd.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 次のコマンドを実行すると、正常にビルドできているかどうかを詳細にテストできます。
172 194 / 194 tests passed. Details in /home/kazubito/yacasl2/test/integration/casl2/Test.log
173 All tests are succeded.
174 149 / 149 tests passed. Details in /home/kazubito/yacasl2/test/integration/comet2/Test.log
175 All tests are succeded.
176 4 / 4 tests passed. Details in /home/kazubito/yacasl2/test/integration/dumpword/Test.log
177 All tests are succeded.
180 @section 環境設定@var{PATH}の設定
182 環境変数@var{PATH}にYACASL2のディレクトリーを追加すると、どのディレクトリーでも@command{casl2}、@command{comet2}、@command{dumpword}を実行できます。
184 環境変数の設定方法は使っているシェルによって異なります。シェルは、次のコマンドで確認できます。現在もっとも多く使われているのは、BASHでしょう。
190 シェルがBASHの場合、次のコマンドを実行すると環境変数@var{PATH}にYACASL2のディレクトリーが追加されます。
192 $ @b{PATH=$PATH:~/yacasl2 && export PATH}
195 シェルの初期設定ファイルに上記のコマンドを追加すれば、今後ログインした後は自動的にどのディレクトリーでも @command{casl2}、@command{comet2}、@command{dumpword}を実行できるようになります。BASHの場合はホームディレクトリーにある@file{.bashrc}が初期設定ファイルのため、コマンドは次のようになります。
197 $ @b{echo ’PATH=$PATH:~/yacasl2 && export PATH’ >>~/.bashrc}
200 @chapter YACASL2 の使い方
202 YACASL2 は、テキストファイルに記述されたCASLプログラムを処理します。以下の例で用いられるCASLプログラムのファイルは、テキストエディタなどで作成してください。また、インストールしたディレクトリーの中にある@file{as}ディレクトリーからコピーして作成することもできます。
204 @section 実行結果の出力だけを表示
206 インストール時にコマンド実行の確認に使った@file{hello.casl}は、次のような内容です。CASL IIのマクロ命令OUTは、文字列を出力します。
212 OBUF DC ’Hello, World!’
217 次のコマンドを実行すると、CASL II のアセンブルと仮想マシン COMET II 上での実行が連続で行われ、文字列が出力されます。
219 $ @b{casl2 hello.casl}
223 @file{addl.casl}は、3と1の和を求めます。
237 このプログラムには出力命令がないため、オプションなしで実行した場合には結果が出力されません。
240 $ @b{casl2 addl.casl}
244 実行内容を確認するには、後述のようにCPU 内にあるレジスターやメモリーの内容を表示するか、結果を出力するための処理を追加する必要があります。
246 @file{sum_10.casl}は、1から10までの整数の和を求めます。
249 $ @b{cat sum_10.casl}
251 ;;; 出力 GR0: 1から10までの整数をすべて加算した値
255 LD GR1,FST ; GR1に初項を転送
256 LOOP ADDL GR0,GR1 ; ループ先頭
257 ADDL GR1,STEP ; GR1 <- GR1 + 公差
258 CPL GR1,LST ; GR1が末項より大きい場合は終了
269 このプログラムも、オプションなしで実行した場合には結果が出力されません。
271 $ @b{casl2 sum_10.casl}
276 casl2の処理途中で行われるアセンブルの結果を表示するには、オプション@option{-a}を指定します。また、ラベルとアドレスの対応表を表示するには、オプション@option{-l}を指定します。
278 次のコマンドでは@file{hello.casl}の、ラベルとアドレスの対応表と、アセンブル結果と、実行結果が表示されます。OUTはアセンブラ命令で複数の機械語命令で構成されているため、命令行1行に対して、複数行のコードが生成されます。
281 $ @b{casl2 -a -l hello.casl}
283 Assemble hello.casl (0)
290 Assemble hello.casl (1)
291 hello.casl: 1:MAIN START
292 hello.casl: 2: OUT OBUF,LEN
315 hello.casl: 4:OBUF DC 'Hello, World!'
329 hello.casl: 5:LEN DC 13
335 @file{addl.casl}の、ラベルとアドレスの対応表と、アセンブル結果は、次のようになります。
338 $ @b{casl2 -a -l addl.casl}
340 Assemble addl.casl (0)
347 Assemble addl.casl (1)
348 addl.casl: 1:;;; ADDL r,adr
349 addl.casl: 2:MAIN START
350 addl.casl: 3: LD GR1,A
353 addl.casl: 4: ADDL GR1,B
365 なお、オプション@option{-A}を指定すると、アセンブル結果が表示される時点で処理が終了します。仮想マシンCOMET II での実行は行われません。
367 @section 実行時のレジスターとメモリーを表示
368 YACASL2では実行中のCPUのレジスターとメモリーの内容をそれぞれ、@option{-t}と@option{-d}を指定することで表示できます。
370 また、@option{-M}で、仮想マシンCOMET II のメモリー容量を語(16 ビット)単位で指定できます。小さいプログラムを実行するときは、メモリー容量を小さくすれば結果が見やすくなります。
372 @file{addl.casl}に必要なメモリー容量は8語のため、次のようにCPUのレジスターとメモリーの内容を表示できます。
375 $ @b{casl2 -t -d -M8 addl.casl | less}
377 Assemble addl.casl (0)
379 Assemble addl.casl (1)
381 Executing machine codes
383 #0000: GR0: 0 = #0000 = 0000000000000000
384 #0000: GR1: 0 = #0000 = 0000000000000000
385 #0000: GR2: 0 = #0000 = 0000000000000000
386 #0000: GR3: 0 = #0000 = 0000000000000000
387 #0000: GR4: 0 = #0000 = 0000000000000000
388 #0000: GR5: 0 = #0000 = 0000000000000000
389 #0000: GR6: 0 = #0000 = 0000000000000000
390 #0000: GR7: 0 = #0000 = 0000000000000000
391 #0000: SP: 8 = #0008 = 0000000000001000
392 #0000: PR: 0 = #0000 = 0000000000000000
393 #0000: FR (OF SF ZF): 000
395 #0000: adr : 0000 0001 0002 0003 0004 0005 0006 0007
396 #0000: 0000: 1010 0005 2210 0006 8100 0003 0001 0000
398 #0002: GR0: 0 = #0000 = 0000000000000000
399 #0002: GR1: 3 = #0003 = 0000000000000011
400 #0002: GR2: 0 = #0000 = 0000000000000000
401 #0002: GR3: 0 = #0000 = 0000000000000000
402 #0002: GR4: 0 = #0000 = 0000000000000000
403 #0002: GR5: 0 = #0000 = 0000000000000000
404 #0002: GR6: 0 = #0000 = 0000000000000000
405 #0002: GR7: 0 = #0000 = 0000000000000000
406 #0002: SP: 8 = #0008 = 0000000000001000
407 #0002: PR: 2 = #0002 = 0000000000000010
408 #0002: FR (OF SF ZF): 000
410 #0002: adr : 0000 0001 0002 0003 0004 0005 0006 0007
411 #0002: 0000: 1010 0005 2210 0006 8100 0003 0001 0000
413 #0004: GR0: 0 = #0000 = 0000000000000000
414 #0004: GR1: 4 = #0004 = 0000000000000100
415 #0004: GR2: 0 = #0000 = 0000000000000000
416 #0004: GR3: 0 = #0000 = 0000000000000000
417 #0004: GR4: 0 = #0000 = 0000000000000000
418 #0004: GR5: 0 = #0000 = 0000000000000000
419 #0004: GR6: 0 = #0000 = 0000000000000000
420 #0004: GR7: 0 = #0000 = 0000000000000000
421 #0004: SP: 8 = #0008 = 0000000000001000
422 #0004: PR: 4 = #0004 = 0000000000000100
423 #0004: FR (OF SF ZF): 000
425 #0004: adr : 0000 0001 0002 0003 0004 0005 0006 0007
426 #0004: 0000: 1010 0005 2210 0006 8100 0003 0001 0000
429 @subsection 特定のレジスターを表示
431 @file{addl.casl}のレジスターやメモリーの中で、実行中に値が変化しているのはGR1だけです。こうした場合は、@command{grep}を使って表示される内容を絞り込むことで動作を検証しやすくなります。
434 $ @b{casl2 -t addl.casl | grep 'GR1:'}
435 #0000: GR1: 0 = #0000 = 0000000000000000
436 #0002: GR1: 3 = #0003 = 0000000000000011
437 #0004: GR1: 4 = #0004 = 0000000000000100
440 この内容を、先に出力したアセンブル結果と引き比べてください。
441 次の表のように、PRとGR1、命令行が対応していることがわかります。
443 @multitable @columnfractions .3 .3 .4
444 @item PR @tab GR1 @tab 命令行
452 @tab @code{ADDL GR1,B}
455 @subsection プログラム終了時の値を表示
457 @command{grep}と@command{tail}を組み合わせれば、プログラム終了時の値を表示できます。
460 $ @b{casl2 -t addl.casl | grep 'GR1:' | tail -1}
461 #0004: GR1: 4 = #0004 = 0000000000000100
465 $ @b{casl2 -t sum_10.casl | grep 'GR0:' | tail -1}
466 #0010: GR0: 55 = #0037 = 0000000000110111 = '7'
469 @subsection プログラムのステップ数を表示
471 @command{grep}と@command{wc}を組み合わせれば、プログラムのステップ数を表示できます。
474 $ @b{casl2 -t hello.casl | grep 'GR1:' | wc -l}
479 $ @b{casl2 -t addl.casl | grep 'GR1:' | wc -l}
483 @file{sum_10.casl}はプログラム内にループがあるため、ステップ数が大きくなります。
486 $ @b{casl2 -t sum_10.casl | grep 'GR0:' | wc -l}
490 @section アセンブルと実行を別に行う
492 @command{casl2}に@option{-O}<@file{ファイル名}>を指定すると、オブジェクトファイルを作成できます。
495 $ @b{casl2 -Ohello.o hello.casl}
498 作成されたオブジェクトファイルの内容は、@command{od}を使って確認できます。テキストファイルではないため、@command{cat}などでは確認できません。
501 $ @b{od -t x2 hello.o}
502 0000000 7001 0000 7002 0000 1210 0013 1220 0020
503 0000020 f000 0002 1210 0021 1220 0022 f000 0002
504 0000040 7120 7110 8100 0048 0065 006c 006c 006f
505 0000060 002c 0020 0057 006f 0072 006c 0064 0021
506 0000100 000d 000a 0001
510 オブジェクトファイルの実行には、@command{comet2}を使います。
519 CASL2では、1語(16ビット)を単位としてデータが処理されます。
520 @command{dumpword}は、指定した1語を10進数、16進数、2進数で表示します。
524 72: 72 = #0048 = 0000000001001000 = 'H'
530 $ @b{dumpword -- -72}
531 -72: -72 = #FFB8 = 1111111110111000
534 16進数で指定する場合は、次のように指定します。
537 $ @b{dumpword '#0048'}
538 #0048: 72 = #0048 = 0000000001001000 = 'H'