0
0

アセンブラの一般化 General Assembler 'axx'

Last updated at Posted at 2024-02-21

GENERAL ASSEMBLER 'axx.py'

axx.pyはアセンブラを一般化したジェネラル(汎用)アセンブラです。

一般的な書き方をしているので、実行プラットフォームも特定の処理系に依存しません。

DOSファイルの行末のchr(13)も無視するようにしています。pythonが動く処理系だったら動作すると思います。

axxは、パターンデータを用意すれば、任意のプロセッサの命令セットを処理できると思いますが、専用のアセンブラの備えている実用的な機能はサポートされていません。今のヴァージョンは試験的実装です。これから、専用のアセンブラの持つ実用的な機能を実装していくつもりもあります。

・使い方

python axx.py 8048.axx [sample.s]のように使います。

axxは第1引数から、アセンブラのパターンデータを読み込み、パターンデータに基づき第2引数のソースファイルをアセンブルします。第2引数を省略したら、標準入力からソースを入力します。

結果は、標準出力にテキストとして出力され、同時にカレントディレクトリにaxx.outというバイナリファイルが出力されます。

axxでは、アセンブリ言語ソースファイルや標準入力から入力するラインをアセンブリラインと名付けます。

・パターンデータの解説

パターンデータは次のように並んでいます。

mnemonic   operands   error_patterns  binary_list 
mnemonic   operands   error_patterns  binary_list 
mnemonic   operands   error_patterns  binary_list 
:
:

mnemonicは2行目からは省略可です。省略する場合は、スペースを指定して下さい。

省略すると、前行のmnemonicが採用されます。

operandsはない場合があります。error_patternsは省略可です。binary_listは省略不可です。

パターンデータの種類は次の3種類になります。

(1) mnemonic                                binary_list
(2) mnemonic    operands                    binary_list
(3) mnemonic    operands   error_patterns   binary_list

・コメント

パターンファイル内に、'/*'を書くとその行の/*以降がコメントになります。今の所、*/で閉じることはできません。その行の/*以降だけに有効です。

アセンブリラインのコメントは;です。

・大文字・小文字の区別、変数

パターンファイルのmnemonic,operandsの大文字は文字定数として扱われます。小文字にすると、変数として扱われます。mnemonic,operandsからは、変数にその位置に当たる式やシンボルの値が代入されます。

小文字の変数は、error_patternsとbinary_listから参照されます。小文字のaからnは式、oからzはシンボルを表します。

アセンブリラインからは、大文字でも小文字も同じとして受け付けます。

アセンブリラインの式の特殊な変数は'$$'で、現在のロケーションカウンタを表します。

・式、値

代入オペレータとして:=があります。d:=24とすると、変数dに24が代入されます。代入オペレータが持つ値は、代入された値です。

前置オペレータ#は、後に続くシンボルの値を取ります。

前置オペレータ@は、後に続く値が何ビットの桁数からなるかを返します。これをヘビマルマッタオペレータと名付けます。

2項演算子'a'24とすると、aの24ビット目のビットを符号ビットにして符号拡張します。これをSEXオペレータと名付けます。

2項演算子**は、べき乗です。

前置オペレータ!は、後に続くlabelの値を返します。

・エスケープキャラクタ

mnemonic,operands内でエスケープキャラクタ\が使えます。

・error_patterns

error_patternsは、変数と比較演算子を使い、エラーの出る条件を指定します。

エラーパターンは複数指定可で、','で区切って記述します。例えば、次のようです。

a>3;4,b>7;5

この例では、a>3のとき、エラーコード4を返し、b>7のときエラーコード5を返します。

・binary_list

binary_listは、出力するコードを','で区切って指定します。例えば、0x03,#dとすると、0x3の次にdが出力されます。

8048を例に取ります。パターンファイルに

ADD    A,Rn  n>7;5  n|0x68

があるとし、アセンブリラインにadd a,rnを渡すと、n>7のときエラーコード5を返し、add a,r1で、0x69のバイナリが生成されます

・symbol

.setsym symbol n

と書くと、symbolが値nで定義されます。

シンボルは、アルファベット、数字、

symbol定義のz80の例を挙げます。パターンファイル内に

.setsym B 0
.setsym C 1
.setsym D 2
.setsym E 3
.setsym H 4
.setsym L 5
.setsym A 7
.setsym BC 0x00
.setsym DE 0x10
.setsym HL 0x20
.setsym SP 0x30

と書いておくと、シンボルB,C,D,E,H,L,A,BC,DE,HL,SPを、それぞれ0,1,2,3,4,5,7,0x00,0x10,0x20,0x30として定義します。シンボルには、大文字小文字の区別はありません。

パターンファイル中に同じシンボルの定義が複数あると、新しいものが古いものを更新します。すなわち、

.setsym B 0
.setsym C 1
ADD A,s

.setsym NZ 0
.setsym Z  1
.setsym NC 2
.setsym C  3
RET s

とあると、ADD A,CのCは1、RET CのCは3になります。

・記号、数字、アルファベットが混在するシンボルの例

.setsym $s5 21

シンボルの全クリアは.clearsymでします。

.clearsym

・バイナリ出力の例

.setsym BC 0x00
.setsym DE 0x10
.setsym HL 0x20
LD    s,d  (#s&0xf!=0)||(#s>>4)>3;9  s|0x01,d&0xff,d>>8

で、ld bc,0x1234, ld de,0x1234, ld hl,0x1234が、それぞれ、0x01,0x34,0x12、0x11,0x34,0x12、0x21,0x34,0x12を出力します。

・パターンの順番

(1) LD A,(HL)
(2) LD A,d

のように、パターンファイルは上から順に評価されますので、先に置かれたほうが優先します。

この場合、(1)と(2)が逆だと、アセンブリラインのld a,(hl)は、dの値に(hl)を入れることになってしまうので、パターンファイルのLD A,(HL)はLD A,dより先に置いてください。特殊のパターンを先に、一般のパターンを後に置きます。

・label

アセンブルラインからは、ラベルは以下の方法で定義することができます。

label1:
label2: equ 0x10
label3: nop

ラベルでラベルを定義することは以下のようにします。

label4: equ !label1

前置オペレータ!を使っています。

・ORG
ORGは、アセンブルラインから、

org 0x800

とします。

・浮動小数点

例えば、浮動小数点をオペランドに含むプロセッサがあるとし、 MOVF fa,3.14 で、faレジスタに3.14がロードされ、そのオペコードは01とします。その場合、パターンデータは、

MOVF FA,d 0x01,d>>24,d>>16,d>>8,d

となり、アセンブルラインに、movf fa,0f3.14を渡すと、バイナリ出力は、0x01,0xc3,0xf5,0x48,0x40となります。

・数表記

2進数は'0b'のプリフィックスを付けて下さい。

16進数は'0x'のプリフィックスを付けて下さい。

浮動小数点float(32bit)は'0f'のプリフィックスを付けて下さい。

浮動小数点double(float 64bit)は、'0d'のプリフィックスを付けて下さい。

MIPSの例

mips.axx
.setsym $v0 2
.setsym $a0 4
ADDI	x,y,d (e:=(0x20000000|(y<<21)|(x<<16)|d&0xffff))>>24,e>>16,e>>8,e
                                             

代入オペレータ:=を使っています。

$ axx.py mips.axx
>> addi $a0,$v0,9
0x20,0x44,0x00,0x09,
>>

x86_64の命令の一例

x86_64.axx
.setsym rax 0
.setsym rbx 3
.setsym rcx 1
LEAQ r,[s+t*d+e] 0x48,0x8d,0x04,((@d)-1)<<6|t<<3|s,e
$ axx x86_64.axx
>> leaq rax,[rbx+rcx*2+0x10]
0x48,0x8d,0x04,0x4b,0x10,

A64FXのテスト

a64fx.axx
.setsym v0 0
.setsym x0 1
ST1 {x.4\s},[y] 0x01,s,y,0
$ axx.py a64fx.axx
>>  st1 {v0.4s},[x0]
0x01,0x00,0x01,0x00,
>>

・エラーチェック

エラーチェックが甘いです。

コメント

・表記の揺れは許して下さい。

・スカラープロセッサなら動くと思います。行列やベクトルを直接レジスタに格納しているプロセッサはないと思うので。

今後の課題

・オペランドにスペースが書けるようにする。

Version

本体

axx用パターンファイル for Z80 CPU

axx用パターンファイル for 8048 CPU

GitHubリポジトリ

謝辞

問題を出してくれて、ヒントをくれた、師匠の浜田純市さんと東京電子設計と、協力してくれた電気通信大学と、そして、忘れられない誰か達に感謝を述べさせていただきます。ありがとうございます。

0
0
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0