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))