ひょんなことからCASL2について人に教える立場になってしまった。汗
CASLをやったのは〇十年前なので、作りながらはまり箇所をチェックしていくのが一番なんだけど、期間的に厳しいのでとりあえず逆アセンブラでも作って仕様に慣れてよしとしよう。
ほんとはCで作ったほうがいいんだけど、今回は布教を兼ねてサクッとDartで。逆アセンブルができれば、その先も見えてくると思うので、時間をみつけて最終的にはDart版CASL2アセンブラとCOMET2シミュレータの実装まで手を出せたらいいなと思う。
といっても、CASL2アセンブラによってアセンブルされたオブジェクトファイルを読み込んで、逐次的に処理するだけで、至って簡単。
事前にアセンブルされたオブジェクトファイルが必要だけど、今回はCASL2のC実装であるYACASL2で出力したオブジェクトファイルを使用した。
使用例)
YACASL2にあるサンプルCASLファイルをアセンブルしておく。
MAIN START
OUT OBUF,LEN
RET
OBUF DC 'Hello, World!'
LEN DC 13
END
$ casl2.exe -ohello.o as/hello.casl
$ od -t x2 hello.o
0000000 7001 0000 7002 0000 1210 0013 1220 0020
0000020 f000 0002 1210 0021 1220 0022 f000 0002
0000040 7120 7110 8100 0048 0065 006c 006c 006f
0000060 002c 0020 0057 006f 0072 006c 0064 0021
0000100 000d 0a0d 0100 0000
0000107
出力されたオブジェクトファイルを逆アセンプルする。
$ cd casldump
$ pub run bin/main.dart hello.o > reverse.casl
MAIN START
L0000 PUSH #0000,GR1 ; 7001 0000
L0002 PUSH #0000,GR2 ; 7002 0000
L0004 LAD GR1,#0013 ; 1210 0013
L0006 LAD GR2,#0020 ; 1220 0020
L0008 SVC #0002 ; f000 0002
L000a LAD GR1,#0021 ; 1210 0021
L000c LAD GR2,#0022 ; 1220 0022
L000e SVC #0002 ; f000 0002
L0010 POP GR2 ; 7120
L0011 POP GR1 ; 7110
L0012 RET ; 8100
L0013 DC 72 ; 0048 'H'
L0014 DC 101 ; 0065 'e'
L0015 DC 108 ; 006c 'l'
L0016 DC 108 ; 006c 'l'
L0017 DC 111 ; 006f 'o'
L0018 DC 44 ; 002c ','
L0019 DC 32 ; 0020 ' '
L001a DC 87 ; 0057 'W'
L001b DC 111 ; 006f 'o'
L001c DC 114 ; 0072 'r'
L001d DC 108 ; 006c 'l'
L001e DC 100 ; 0064 'd'
L001f DC 33 ; 0021 '!'
L0020 DC 13 ; 000d
L0021 DC 13 ; 0a0d
L0022 DC 0 ; 0100 (might be DS)
END
ラベルは復元できないのでSTARTのMAINラベルは固定、あとはオフセットをそのままラベル化。マクロも展開されたまま。一応、逆アセンブルをファイルに落として再度アセンブルできることは確認した。(あんまりテストしていない。サブルーチンとか?)
Dartでバイナリ操作するのは結構大変そうだなと思っていたがそうでもなかった。しかし、書式の指定が仰々しい。もっとスマートに書けるんかな。
ソースはここ。
https://github.com/tatsu/casldump
以下、Dartメモ。
File#readAsBytesの戻り値がListで使いにくそうだと思ったが、実際はUint8Listなのでupcastするだけで使えた。
https://github.com/dart-lang/sdk/issues/31547
シンボル名を表示しようとすると、リフレクションが必要みたい。いまのところ。
https://github.com/dart-lang/sdk/issues/28372