Copyright © 2010 j8takagi

YACASL2の概要
**********

YACASL2は、Linux上で動作するオープンソースのCASL II処理系です。CASL IIは情報処理試験で用いられるアセンブラ言語で、次の資料により仕様が公開されています。

     試験で使用する情報処理用語・プログラム言語など（2008年10月版） (http://www.jitec.ipa.go.jp/1_00topic/topic_20081027_hani_yougo.pdf)［PDFファイル］別紙 1 アセンブラ言語の仕様

YACASL2は、CASL IIアセンブラ言語で記述されたファイルをアセンブルし、仮想マシンCOMET II上で実行します。アセンブルと実行は、連続で行うことも別々に行うことも可能です。 YACASL2の動作はCASL IIの仕様に準拠しているため、情報処理試験の問題をはじめ各種参考書やサイトに記載されたCASL IIのプログラムをそのままアセンブルして実行できます。また、本パッケージ中にCASL IIのサンプルプログラムが多数収録されています。

YACASL2は、「ふつうの処理系」として動作します。ほかの多くのCASL IIエミュレーターと違い、デバッガーとして動作したり、コンピューター内部の模式図を表示したりすることはありません。そのかわり、YACASL2は、次のような動作内容をすべてテキストで出力します。

  * ラベルとアドレスの対応

  * アセンブル結果

  * 実行時のレジスタの内容

  * 実行時のメモリの内容

出力された動作内容は、GNU/Linuxのさまざまなツール、たとえばhead、tail、grep、diffなどを使って解析できます。

要件
==

YACASL2は、Linux上で動作します。インストール時に、tar、gcc、makeが必要です。

現在動作を確認しているのは、次のディストリビューションです。

  * Ubuntu Linux 9.04 / 8.04

  * Vine Linux 4.2

YACASL2のインストール
**************

YACASL2をインストールするには、Linux上で次の作業をします。

 1. yacasl2.tar.gzのダウンロード

 2. yacasl2.tar.gzの検証

 3. yacasl2.tar.gzの展開

 4. casl2、comet2、dumpwordのビルド

 5. casl2の実行テスト

 6. 詳細なテスト

 7. 環境設定PATHの設定

以下の操作は、端末を開きコマンドを実行します。

yacasl2.tar.gzのダウンロード
=====================

（詳細未定）

     $ cd
     $ wget somewhere/yacasl2.tar.gz
     $ wget somewhere/yacasl2.tar.gz.md5sum

yacasl2.tar.gzの検証
=================

（PGPを使った検証も導入予定）

ダウンロードが完了したら、md5sumとdiffで正しくファイルがダウンロードができているかを検証します。

     $ md5sum yacasl2.tar.gz | diff -s yacasl2.tar.gz.md5sum -
     Files yacasl2.tar.gz.md5sum and - are identical

yacasl2.tar.gzの展開
=================

yacasl2.tar.gzをダウンロードしたら、次のコマンドで展開します。

     $ tar xvzf yacasl2.tar.gz

casl2、comet2、dumpwordのビルド
=========================

展開したら、次のコマンドでcasl2、comet2、dumpwordをビルドします。

     $ cd yacasl2
     $ make
     make -C src
     make[1]: Entering directory ‘/home/kazubito/yacasl2/src’
     gcc -c -g -Wall -I ../include casl2.c
     gcc -c -g -Wall -I ../include word.c
     gcc -c -g -Wall -I ../include hash.c
     gcc -c -g -Wall -I ../include cerr.c
     gcc -c -g -Wall -I ../include struct.c
     gcc -c -g -Wall -I ../include cmd.c
     gcc -c -g -Wall -I ../include assemble.c
     gcc -c -g -Wall -I ../include token.c
     gcc -c -g -Wall -I ../include label.c
     gcc -c -g -Wall -I ../include macro.c
     gcc -c -g -Wall -I ../include exec.c
     gcc -c -g -Wall -I ../include dump.c
     gcc -g -Wall -I ../include -o ../casl2 casl2.o word.o hash.o cerr.o st
     ruct.o cmd.o assemble.o token.o label.o macro.o exec.o dump.o
     gcc -c -g -Wall -I ../include comet2.c
     gcc -g -Wall -I ../include -o ../comet2 comet2.o word.o hash.o cerr.o
     struct.ocmd.o exec.o dump.o
     gcc -c -g -Wall -I ../include dumpword.c
     gcc -g -Wall -I ../include -o ../dumpword dumpword.o word.o cerr.o
     make[1]: Leaving directory ‘/home/kazubito/yacasl2/src’

casl2の実行テスト
===========

ビルドしたら、次のコマンドが正常に実行できるかを確認します。正常に実行された場合は、「Hello, World!」と表示されます。

     $ ./casl2 as/hello.casl
     Hello, World!

詳細なテスト
======

次のコマンドを実行すると、正常にビルドできているかどうかを詳細にテストできます。

     $ make check

環境設定PATHの設定
===========

環境変数PATHにYACASL2のディレクトリーを追加すると、どのディレクトリーでもcasl2、comet2、dumpwordを実行できます。

環境変数の設定方法は使っているシェルによって異なります。現在もっとも多く使われているシェルは、Bashでしょう。次のコマンドで使っているシェルを確認できます。

     $ echo $SHELL
     /bin/bash

シェルがBashの場合、次のコマンドを実行すると環境変数PATHにYACASL2のディレクトリーが追加されます。

     $ PATH=$PATH:~/yacasl2 && export PATH

シェルの初期設定ファイルに上記のコマンドを追加すれば、今後ログインした後は自動的にどのディレクトリーでも casl2、comet2、dumpwordを実行できるようになります。Bashの場合はホームディレクトリーにある.bashrcが初期設定ファイルのため、コマンドは次のようになります。

     $ echo ’PATH=$PATH:~/yacasl2 && export PATH’ >>~/.bashrc

YACASL2 の使い方
************

YACASL2 は、テキストファイルに記述されたCASLプログラムを処理します。以下の例で用いられるCASLプログラムのファイルは、テキストエディタなどで作成してください。また、インストールしたディレクトリーの中にあるasディレクトリーからコピーして作成することもできます。

実行結果の出力だけを表示
============

hello.casl
----------

インストール時にコマンド実行の確認に使ったhello.caslは、次のような内容です。CASL IIのマクロ命令OUTは、文字列を出力します。

     $ cat hello.casl
     MAIN     START
              OUT     OBUF,LEN
              RET
     OBUF     DC      ’Hello, World!’
     LEN      DC      13
              END

次のコマンドを実行すると、CASL II のアセンブルと仮想マシン COMET II 上での実行が連続で行われ、文字列が出力されます。

     $ casl2 hello.casl
     Hello, World!

addl.casl
---------

3 と 1 の和を求めるaddl.caslは、次のような内容です。

     $ cat addl.casl
     ;;; ADDL r,adr
     MAIN     START
              LD      GR1,A
              ADDL    GR1,B
              RET
     A        DC      3
     B        DC      1
              END

このプログラムには出力命令がないため、オプションなしで実行した場合には結果が出力されません。

     $ casl2 addl.casl
     $

実行内容を確認するには、後述のようにCPU 内にあるレジスターやメモリーの内容を表示するか、結果を出力するための処理を追加する必要があります。

アセンブル結果の確認
==========

casl2の処理途中で行われるアセンブルの結果を表示するには、オプション-aを指定します。また、ラベルとアドレスの対応表を表示するには、オプション-lを指定します。

hello.casl
----------

次のコマンドでは、hello.caslのラベルとアドレスの対応表と、アセンブル結果と、実行結果が表示されます。OUTはアセンブラ命令で複数の機械語命令で構成されているため、命令行1行に対して、複数行のコードが生成されます。

     $ casl2 -a -l hello.casl

     Assemble hello.casl (0)

     Label::::
     MAIN.LEN ---> #0020
     MAIN ---> #0000
     MAIN.OBUF ---> #0013

     Assemble hello.casl (1)
     hello.casl:    1:MAIN    START
     hello.casl:    2:        OUT     OBUF,LEN
         #0000   #7001
         #0001   #0000
         #0002   #7002
         #0003   #0000
         #0004   #1210
         #0005   #0013
         #0006   #1220
         #0007   #0020
         #0008   #F000
         #0009   #0002
         #000A   #1210
         #000B   #0021
         #0021   #000A
         #000C   #1220
         #000D   #0022
         #0022   #0001
         #000E   #F000
         #000F   #0002
         #0010   #7120
         #0011   #7110
     hello.casl:    3:        RET
         #0012   #8100
     hello.casl:    4:OBUF    DC      'Hello, World!'
         #0013   #0048
         #0014   #0065
         #0015   #006C
         #0016   #006C
         #0017   #006F
         #0018   #002C
         #0019   #0020
         #001A   #0057
         #001B   #006F
         #001C   #0072
         #001D   #006C
         #001E   #0064
         #001F   #0021
     hello.casl:    5:LEN     DC      13
         #0020   #000D
     hello.casl:    6:        END
     Hello, World!

addl.casl
---------

addl.caslのラベルとアドレスの対応表と、アセンブル結果は、次のようになります。

     $ casl2 -a -l addl.casl

     Assemble addl.casl (0)

     Label::::
     MAIN.A ---> #0005
     MAIN.B ---> #0006
     MAIN ---> #0000

     Assemble addl.casl (1)
     addl.casl:    1:;;; ADDL r,adr
     addl.casl:    2:MAIN    START
     addl.casl:    3:        LD      GR1,A
         #0000   #1010
         #0001   #0005
     addl.casl:    4:        ADDL    GR1,B
         #0002   #2210
         #0003   #0006
     addl.casl:    5:        RET
         #0004   #8100
     addl.casl:    6:A       DC      3
         #0005   #0003
     addl.casl:    7:B       DC      1
         #0006   #0001
     addl.casl:    8:        END

なお、オプション-Aを指定すると、アセンブル結果だけが表示され、仮想マシンCOMET II での実行は行われません。

実行時のレジスターとメモリーを表示
=================

YACASL2では実行中のCPUのレジスターとメモリーの内容をそれぞれ、-tと-dを指定することで表示できます。

また、-Mで、仮想マシンCOMET II のメモリー容量を語(16 ビット)単位で指定できます。小さいプログラムを実行するときは、メモリー容量を小さくすれば結果が見やすくなります。

addl.casl
---------

addl.caslに必要なメモリー容量は8語のため、次のようにCPUのレジスターとメモリーの内容を表示できます。

     $ casl2 -t -d -M8 addl.casl | less

     Assemble addl.casl (0)

     Assemble addl.casl (1)

     Executing machine codes
     #0000: Register::::
     #0000: GR0:      0 = #0000 = 0000000000000000
     #0000: GR1:      0 = #0000 = 0000000000000000
     #0000: GR2:      0 = #0000 = 0000000000000000
     #0000: GR3:      0 = #0000 = 0000000000000000
     #0000: GR4:      0 = #0000 = 0000000000000000
     #0000: GR5:      0 = #0000 = 0000000000000000
     #0000: GR6:      0 = #0000 = 0000000000000000
     #0000: GR7:      0 = #0000 = 0000000000000000
     #0000: SP:       8 = #0008 = 0000000000001000
     #0000: PR:       0 = #0000 = 0000000000000000
     #0000: FR (OF SF ZF): 000
     #0000: Memory::::
     #0000: adr : 0000 0001 0002 0003 0004 0005 0006 0007
     #0000: 0000: 1010 0005 2210 0006 8100 0003 0001 0000
     #0002: Register::::
     #0002: GR0:      0 = #0000 = 0000000000000000
     #0002: GR1:      3 = #0003 = 0000000000000011
     #0002: GR2:      0 = #0000 = 0000000000000000
     #0002: GR3:      0 = #0000 = 0000000000000000
     #0002: GR4:      0 = #0000 = 0000000000000000
     #0002: GR5:      0 = #0000 = 0000000000000000
     #0002: GR6:      0 = #0000 = 0000000000000000
     #0002: GR7:      0 = #0000 = 0000000000000000
     #0002: SP:       8 = #0008 = 0000000000001000
     #0002: PR:       2 = #0002 = 0000000000000010
     #0002: FR (OF SF ZF): 000
     #0002: Memory::::
     #0002: adr : 0000 0001 0002 0003 0004 0005 0006 0007
     #0002: 0000: 1010 0005 2210 0006 8100 0003 0001 0000
     #0004: Register::::
     #0004: GR0:      0 = #0000 = 0000000000000000
     #0004: GR1:      4 = #0004 = 0000000000000100
     #0004: GR2:      0 = #0000 = 0000000000000000
     #0004: GR3:      0 = #0000 = 0000000000000000
     #0004: GR4:      0 = #0000 = 0000000000000000
     #0004: GR5:      0 = #0000 = 0000000000000000
     #0004: GR6:      0 = #0000 = 0000000000000000
     #0004: GR7:      0 = #0000 = 0000000000000000
     #0004: SP:       8 = #0008 = 0000000000001000
     #0004: PR:       4 = #0004 = 0000000000000100
     #0004: FR (OF SF ZF): 000
     #0004: Memory::::
     #0004: adr : 0000 0001 0002 0003 0004 0005 0006 0007
     #0004: 0000: 1010 0005 2210 0006 8100 0003 0001 0000

addl.caslのレジスターやメモリーの中で、実行中に値が変化しているのはGR1だけです。こうした場合は、grepを使って表示される内容を絞り込むことで動作を検証しやすくなります。

     $ casl2 -t addl.casl | grep 'GR1:'
     #0000: GR1:      0 = #0000 = 0000000000000000
     #0002: GR1:      3 = #0003 = 0000000000000011
     #0004: GR1:      4 = #0004 = 0000000000000100

ここで、先に実行したaddl.caslのアセンブル結果をもう一度見てください。次の表のように、PRとGR1、命令行が対応していることがわかります。

PR   GR1   命令行
#0000
#0000
#0002
#0003
LD GR1,A
#0004
#0004
ADDL GR1,B