CASL Assembler / Simulator
require "rasl"
app = Rasl::Processor.new
app.assemble <<-SOURCE
MAIN START
LD GR0,=1
LD GR1,=2
ADDA GR0,GR1
ST GR0,RESULT
RET
RESULT DS 1
END
SOURCE
app.go
app.gr[:gr0].value # => 3
app.labels["MAIN"] # => {"RESULT"=>8}
app.memory[app.labels["MAIN"]["RESULT"]] # => 3
puts app.disassemble
# >> 0000 1000 0009 LD GR0, #0009
# >> 0002 1010 000A LD GR1, #000A
# >> 0004 2401 ADDA GR0, GR1
# >> 0005 1100 0008 ST GR0, #0008
# >> 0007 8100 RET
# >> 0008 0003 DC 3
# >> 0009 0001 DC 1
# >> 000A 0002 DC 2
仕様
- プロシージャ
- START〜END は複数定義可
- START に前置するラベルは必須ではない
- START と END は省略可
- 最初に登場した START の引数をブートアドレスにする
- ラベル
- STARTに前置したラベルはグローバルラベル
- STARTのあとからENDまではローカルラベル
- ラベルの文字数制限なし
- ラベルの最後にコロンをつけてもよい (ラベルに含まない)
- ラベルの最後にコロンをつけると必ずラベルになる (NOP: と書いたら NOP は命令ではなくラベルとみなす)
- ラベルの先頭に $ や @ をつけてもよい (ラベルに含む)
- $ で始まるラベルは必ずグローバルラベルになる
- ラベルだけの行を書いてもよい
- ラベルは大小文字を区別する
- START〜ENDを書かなかった場合のラベルはすべてグローバルラベル
- 構文
- スペースを空けずに命令を書いてもよい (Rasl.config.bol_order = false で無効になる)
- 引数のセパレーターはスペースでもいい
- インライン即値の部分は “= 1” のようにスペースを空けてもよい
- 文字列はダブルクォーテーションで囲んでもいい
- 行頭からだけ # でコメントにできる。shebang 用
- その他
- CASL1 と CASL2 に対応
- インライン即値はENDの直前に定義する。END がなければコードの最後に定義する
- EXIT で終了してもよい
- GRn を n とは書けない (CASL2ではアドレスとレジスタの区別がつかないため)
- NOP は #00 にはしてない (データなのか命令なのかまぎらわしいので)
- GRn の他に FR PC SP レジスタを指定できる (例: addl SP, 1 など)
- Rasl.config.spec = 1 にすると GR4 が SP になる
- 注意
- 文字コードは UTF-8 なので DC ‘あ’ は DS 3 の領域を使う
- 文字列リテラルの中だろうとセミコロン以降をぶっちぎる。 ‘a;b’ の場合 ‘a となるため \ でエスケープして ‘a\;b’ と書く
コマンドラインで使う例
–help
$ rasl --help CASL Assembler / Simulator rasl 0.0.1 使い方: rasl [OPTIONS] [ファイル] -s, --simulator シミュレータ起動 -p, --print-map MAP情報の標準出力 -m, --output-map MAP情報のファイル出力。-g オプションがあるときは実行後に出力する -g, --go 実行 -e, --eval=CODE 指定コードの評価。指定があると標準入力からは読み込まない --memory-size=SIZE メモリサイズの指定(デフォルト:65536) --spec=NUMBER 1:レジスタ数5個でGR4==SP 2:レジスタ数8 GR4!=SP --ds-init-value=VAL DSで領域確保したときの初期値(デフォルト:0) --memory-defval=VAL メモリの初期値(デフォルト:0) --[no-]bol-order 命令の前に空白を書かなくてよいことにする(デフォルト:true) -i, --register 実行後レジスタ一覧表示
MAP情報の標準出力 (-p)
$ rasl -p hello.csl 0000 7001 0000 PUSH #0000, GR1 0002 7002 0000 PUSH #0000, GR2 0004 1210 000D LAD GR1, #000D 0006 1220 0018 LAD GR2, #0018 0008 F000 0001 SVC #0001 000A 7120 POP GR2 000B 7110 POP GR1 000C 8100 RET 000D 0048 DC 72 ; 'H' 000E 0065 DC 101 ; 'e' 000F 006C DC 108 ; 'l' 0010 006C DC 108 ; 'l' 0011 006F DC 111 ; 'o' 0012 000B DC 5
MAP情報のファイル出力 (-m)
$ rasl -m hello.csl $ cat hello.map 0000 7001 0000 PUSH #0000, GR1 0002 7002 0000 PUSH #0000, GR2 0004 1210 000D LAD GR1, #000D 0006 1220 0018 LAD GR2, #0018 0008 F000 0001 SVC #0001 000A 7120 POP GR2 000B 7110 POP GR1 000C 8100 RET 000D 0048 DC 72 ; 'H' 000E 0065 DC 101 ; 'e' 000F 006C DC 108 ; 'l' 0010 006C DC 108 ; 'l' 0011 006F DC 111 ; 'o' 0012 000B DC 5
指定コードの評価 (-e)
$ rasl -p -e 'LEA GR1,1,GR1' 0000 1F11 0001 LEA GR1, #0001, GR1
標準入力から渡してもよい
$ echo 'LEA GR1,1,GR1' | rasl -p 0000 1F11 0001 LEA GR1, #0001, GR1
実行 (-g)
$ rasl -g hello.csl Hello
Simulator (-s)
$ rasl -s hello.csl -? D[address] memory-dump U[address] unassemble G[address] go T[address] trace R[reg=n] register ? or H usage I init Q quit -r GR0=0000 GR1=0000 GR2=0000 GR3=0000 GR4=0000 GR5=0000 GR6=0000 GR7=0000 PC=0000 SP=FFFF FR=___(+) 0000 7001 0000 PUSH #0000, GR1 -t GR0=0000 GR1=0000 GR2=0000 GR3=0000 GR4=0000 GR5=0000 GR6=0000 GR7=0000 PC=0002 SP=FFFE FR=___(+) 0002 7002 0000 PUSH #0000, GR2 -t GR0=0000 GR1=0000 GR2=0000 GR3=0000 GR4=0000 GR5=0000 GR6=0000 GR7=0000 PC=0004 SP=FFFD FR=___(+) 0004 1210 000D LAD GR1, #000D -u 0000 7001 0000 PUSH #0000, GR1 0002 7002 0000 PUSH #0000, GR2 0004 1210 000D LAD GR1, #000D 0006 1220 0012 LAD GR2, #0012 0008 F000 0001 SVC #0001 000A 7120 POP GR2 000B 7110 POP GR1 000C 8100 RET -g Hello -d0 0000: 7001 0000 7002 0000 1210 000D 1220 0012 ........ 0008: F000 0001 7120 7110 8100 0048 0065 006C .....Hel 0010: 006C 006F 0005 0000 0000 0000 0000 0000 lo...... 0018: 0000 0000 0000 0000 0000 0000 0000 0000 ........ -q
IN 命令時の __END__
デフォルトでは標準入力待ちになるが __END__ の指定があればその次の行からを入力データとして扱う
$ cat in_out.csl
START
IN STR,LEN ; STR="a" LEN=1
OUT STR,LEN ; => "a"
IN STR,LEN ; STR="" LEN=0
OUT STR,LEN ; => ""
IN STR,LEN ; STR="b" LEN=1
OUT STR,LEN ; => "b"
IN STR,LEN ; STR="" LEN=-1
OUT STR,LEN ; => なし
RET
STR DS 4
LEN DS 1
END
__END__
a
b
$ rasl -g in_out.csl
a
b
オススメの Emacs 設定
(add-to-list 'auto-mode-alist '("\\.\\([rc]asl?\\|csl\\)$" . asm-mode))