Skip to content

本プログラムはLinux上で動作する独自仕様のコンパイラです、asm_x64やARM CPUのアセンブラソースコードを出力します。

License

Notifications You must be signed in to change notification settings

kousoz80/oregengo_R

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

25 Commits
 
 
 
 
 
 
 
 
 
 

Repository files navigation

oregengo_R

本プログラムはLinux上で動作する独自仕様のコンパイラであり、asm_x64アセンブラソースコードを出力します。

[動作画面]

oregengo_R

[ビルド]

以下のコマンドをタイプするとコンパイラの実行可能ファイルが作成されます。

gcc -o [コンパイラの実行可能ファイル名] compiler.c

[使用方法]

以下のコマンドをタイプするとasm_x64形式のアセンブラソースファイルが作成されます。

./(コンパイラの実行可能ファイル名) stdio.rh ソースファイル

ファイル"stdio.rh"は付属のヘッダ・ライブラリファイルです。

また出力されるアセンブラソースファイル名は"asm.s"で固定されています。

出来上がったアセンブラソースファイルをアセンブルすると実行可能ファイルが作成されます。

java -jar asm_x64.jar asm.s [実行可能ファイル名]

[エラーメッセージ]

現在のところエラー出力は未実装の状態です。エラーはアセンブルするとき出ます。
アセンブラソースのエラーの出る箇所で、ソースファイルの不具合を出る部分を推定して修正しています。

[文法]

このコンパイラのソースファイルは数式をRPN(逆ポーランド記法)で記述します
  RPNとは数式をあらわすのに使われる表記方の1つで 通常の数式とは逆の順序で表わされます。

例えば一般的なプログラムの数式の記述では、b とc を足してaに代入することを

a=b+c と書きますが

逆ポーランド記法では例えば

b, c, + a=

のように表記します。

以下にこのソースファイルの表記法を述べます。

(1) 宣言文

1. 64ビット整数の宣言

-2^63 から2^63-1までの整数を宣言します

long a#,b#

2. 32ビット整数の宣言

0から2^32-1までの整数を宣言します

int a!,b!

2. 16ビット整数の宣言

0から65535までの整数を宣言します

short a%,b%

3. 8ビット整数の宣言

0から255までの整数を宣言します

char a$,b$

1つの文中に最大8個までの整数の宣言ができます。

2.配列変数の宣言

long aa#(10),bb#(20)

int a!(10),b!(20)

short c%(30),d%(40)

char e$(50), f$(60)

配列変数は単純変数と違って1つの文中に最大4個までしか宣言できません。

配列変数は1次元配列だけです。

また、単純変数と配列変数を同じ文中で宣言することはできません。

3.カウンタ型変数の宣言

count i#,j#,k#

本コンパイラではfor-next文に対応するため特殊な64ビット型の整数を用意しています。 数値の範囲はlong型の整数と同じです。

この型の変数を宣言するとfor-next文のためのワークエリアが確保されます

上の例は次のようにかきなおすことができます。

long i#(4),j#(4),k#(4)

注… カウンタ型の配列変数は存在しません。

またCPUのレジスタ名と同じ名前の変数は使用しないで下さい。

4.定数の宣言

形式

const 定数1 値1

]定数1に値1を割り付けます

const XXX 12 /* xxxに12を割り付ける */

なお本コンパイラにはあらかじめ以下のような定数が組み込まれています

const EOF 255 /* ファイルの終わりをあらわす文字コード */

const ERROR -1 /* エラーが発生したことをあらわす */

const NULL 0 /* ヌルポインタ */

const SPACE 32 /* 空白文字 */

const CR 13 /* キャリッジリターンコード */

const LF 10 /* ラインフィードコード */

const PLUS 43 /* プラス記号の文字コード */

const MINUS 45 /* マイナス記号の文字コード */

const ESC 27 /* ESCキーの文字コード */

(2) if-then文

形式

if 値1(条件) 値2 then 文1

条件が成立したとき文1を実行します

if a%>=b% then .... /* 変数a$が変数b%以上のとき...

if a$=b$ then ... /* 変数a$が変数b$と等しいとき...

if a%<b$ then .... /* 変数a%が変数b$より小さいとき...

if a!<=1 then... /* 変数a!が1以下のとき...

if 2<>b$ then ... /* 2と変数b$が異なるとき...

上の例からも分かるように違う型の変数でも比較できます。

条件は次の6種類です

< …小さい

> …大きい

<= …以下

>= …以上

= …等しい

<> …等しくない

注意...このif-then文はネスティングができません。

また if-then-elseではないので注意してください。

(3) if-goto文

形式

if 値1 (条件) 値2 goto ラベル1

条件が成立したときにラベル1にジャンプします。

条件はif-then文の時と同じです。

(4) for-next文

形式

for 変数1=値1 to 値2 [ step 値3 ]

next 変数1

BASICのfor-next文と同様ですがnextの後の変数名は省略できません。

例1

for i#=1 to 10

next i#

for j#=i!% to k$ step n%

next j#

(5) goto文

形式

goto ラベル1

gotoラベル2

BASICのgoto文と同じです

goto label1

gotolabel2

goto label3

(6)data文

形式

data 値1[,値2,...値8]

BASICのdata文とほとんど同じものですが、1行に最大8個までの数値や文字列しか書く事ができないので注意して下さい。

(7)end文

形式

end

メインプログラムのなかではプログラムの実行を終了し、サブルーチンのなかでは呼び出したプログラムに帰ります。

(8)return文

形式

return

end文と同じ動作をします。

(9) 式の評価と代入

数値を格納するためにCPU上のレジスタが割り当てられています。

1.単純な値の代入

値1,

の形式の文があると、CPUは値1をスタックにpushします。

そして

変数1=

の形式の文があればCPUはスタックトップの値を変数1に代入します。

aa!, bb%= /* aa!の値がbb%に代入される */

1, aa%= /* aa%に1が代入される */

aa$(1), cc%= /* aa$(1)の値がcc%に代入される */

dd%, cc$(j!)= /* dd%の値がcc$(j!)に代入される */

XXX, dd$= /* 定数XXXの値が変数dd$に代入される */

以下のものは同じものとみなせます("≡"は同じものという意味)。

aa!≡aa!(0)

aa+0$≡aa$(0)≡aa$

aa+1$≡aa$(1)

aa+2$≡aa$(2)

aa+2%≡aa%(1) (オフセットがインデックスの2倍になっている)

aa+4%≡aa%(2) 〃

aa+8!≡aa!(2) (オフセットがインデックスの4倍になっている)

aa$≡( aa%の下位8ビット )

aa$(1)≡( aa%の上位8ビット )

aa≡( 変数aa%やaa$のアドレス(定数) )

XX$≡( XX番地のメモリの内容 )

1234$≡( 1234番地のメモリの内容 )

2.加減乗除算

次の記号がでてくるとマシンは以下の操作をします。

+ (スタックトップの値とその次の値を足した値をスタックトップに格納する)

ー (スタックトップの値をその次の値から引いた値をスタックトップに格納する)

* (スタックトップの値とその次の値に乗じてスタックトップに格納する)

/ (スタックトップの値でその次の値を割った値をスタックトップに格納する)

1, 2, + aa%= /* aa%に3が入る */

3, 4, - bb%= /* bb%に-1が入る */

bb%, cc%, * dd$= /* dd$にbb%とcc%をかけた値が入る */

aa%, dd, / aa%= /* aa%に変数dd%のアドレスで割った値が入る */

ss%, XX, + kk$= /* kk$にss%と定数XXを足した値が入る */

3.ポインタ

64ビット整数はポインタとして用いることができます。

int p!,q!,r!,j!

short aa%(10)

int bb!(10)

char cc$(10)

aa, p#=

bb, q#=

cc, r#=

とした時に以下のものは同じものとみなせます

short型の場合

(p)%≡aa%≡aa%(0)

(p)%(1)≡aa%(1)

(p)%(j#)≡aa%(j#)

この後、次の文を実行すると以下のものは同じものとみなせます

p!, 2, + p!=

(short型ではポインタのオフセットと配列のインデックスが2倍の関係になっていることに注意。)

(p)%≡(p)%(0)≡aa%(1)

(p)%(1)≡aa%(2)

int型の場合

(q)!≡bb!≡bb!(0)

(q)!(1)≡bb!(1)

(q)!(j!)≡bb!(j!)

この後、次の文を実行すると以下のものは同じものとみなせます

q!, 8, + q!=

(int型ではポインタのオフセットと配列インデックスが4倍の関係になっていることに注意。)

(q)!≡(q)!(0)≡bb!(2)

(q)!(1)≡bb!(3)

char型の場合

(r)$≡cc$≡cc$(0)

(r)$(1)≡cc$(1)

(r)$(j#)≡cc$(j#)

この後、次の文を実行すると以下のものは同じものとみなせます

r#, 3, + r#=

(char型ではポインタのオフセットと配列インデックスが等倍の関係になっていることに注意。)

(r)$≡(r)$(0)≡cc$(3)

(r)$(1)≡cc$(4)

(10)文字列

8ビット整数の集まりを文字列と呼びます。

本コンパイラでは引用符"で文字列を囲むとその文字列がメモリ上に確保され、その文字列のアドレスがスタックトップに格納されます。

"abcd", p#= を実行するとそれぞれ、

(p)$(0) = 'a'

(p)$(1) = 'b'

(p)$(2) = 'c'

(p)$(3) = 'd'

となっていることが確かめられます。

(11) 関数

数値を扱う関数はスタックの値を参照して結果をスタックトップに返します。

あるいは値を返さない関数(サブルーチン)もあります。

1.関数定義,呼び出し

/* メイン関数:プログラムはここから実行される(この関数は必須) */

main:

int i%,j%,k%

i%, j%, funct1 k%= /* 変数i%, j%の値をスタックにpushして関数func1を呼び出す */

/* そして戻り値を変数k%に格納する */

end

/* 関数名はラベルで定義する */

funct1:

int ii%, jj%, kk%

jj%= pop ii%= /* 結果的にi%の値がii%に,j%の値がkk%に入る(関数popについては後述) */

kk%, return /* 戻り値をスタックにpushしてリターン */

2.組込関数

本コンパイラでは以下の関数を用意しています。

abs...絶対値を返す

-1, abs k%= /* k%に1が入る */

pop...レジスタ・スタックの値をpopする

2, 3, 4, i%= pop j%= pop k%= /* i%に4、j%に3、k%に2が入る */

swap...スタックトップとその次の値を交換する

4, 5, j%= swap k%= /* j%に5, k%に4が入る */

restore...read関数の読み取り位置を決める(注意:最初のread関数を実行する前に必ず実行しなければならない)

read...data文から値を読み取る

data_start, restore

read j%=

read s!=

read a$=

read x$=

data_start:

data 1000,"abcdef"

data 10

putchar...1文字表示

'A', putchar

inputs...キーボードから文字列を入力

prints...文字列表示

nl...改行する

char ss$(64)

ss, inputs

ss, prints

"abcdefg", prints nl

printd...数値を表示する

1234, k!=

k!, printd

1234, printd

strcpy...文字列のコピー

strcat...文字列の追加

strlen...文字列の長さを返す

strstr...文字列のある場所(アドレス)を返す

char ss$(64)

"13456ABCDEF", ss, strcpy

ss, "ghi", strcat /* ssには"13456ABCDEFghi"が入る */

ss, strlen k#= /* k#には14が入る */

ss, "ABC", strstr k#= /* k#にはss+5が入る */

atoi ...文字列を数値に変換する(基数を指定すること)

"1010", 10, atoi k!= /* k!には1010が入る */

"1010", 16, atoi k!= /* k!には5112入る */

"1010",2, atoi k!= /* k!には10が入る */

hex ...数値を16進数の文字列に変換する

255, hex ss, strcpy /* ssには"ff"が入る */

dec ...数値を10進数の文字列に変換する

1234, dec prints /* "1234"と表示される */

oct ...数値を8進数の文字列に変換する

bin ...数値を2進数の文字列に変換する

ropen ....ファイルを読み出しモードでオープンする

wopen ....ファイルを書き込みモードでオープンする

getc ....ファイルから1文字入力する

putc ....ファイルへ1文字出力する

finputs ...ファイルから1行文字列を入力する

fprints ...ファイルへ文字列を出力する

fprintd ...ファイルへ数値を出力する

fnl .....ファイルへ改行コードを出力する

close ....ファイルのクローズ

long hrd#,hwr# /* ファイルハンドル */

char cc$

char ss$(64)

"input.txt", ropen hrd#=

"output.txt", wopen hwr#=

hrd#, getc cc$=

cc$, hwr#, putc

ss, hrd#, finputs

ss, hwr#, fprints

ss, strlen hwr#, fprintd

hwr#, fnl

hrd#, close

hwr#, close

(12) インラインアセンブラ

   行の前後を "/"(スラッシュ)で囲むと囲まれた部分をアセンブラ命令として解釈します

(最初の"/"は行の1桁目でないと除算演算子として解釈されるので注意)

i%, func j%=

/* 渡された数値を2倍にする */

func:

/ rax=rdi/

/ rdi+=rax/

end
 
(13) プログラムの例

1. "hello world"を表示するプログラム

main:

"hello world", prints nl

end

2.1から10までを表示するプログラム

count i#

main:

for i#=1 to 10

i#, printd nl

next i#

end

3.ファイル"abc"の内容を表示するぷろぐらむ

long hf#

char cc$

main:

"abc", ropen hf#=

if hf#=ERROR then "ファイルがありません", prints end

main_loop:

hf#, getc cc$=

if cc$=EOF goto exit_loop

cc$, putchar

goto main_loop

exit_loop:

hf#, close

end

4.ファイル"abc"から指定された文字列を見つけるプログラム

long line#,p#,hf#

char buf$(80),ss$(16)

char f$

main:

1, line#=

"文字列? ", prints ss, inputs

"abc", ropen hf#=

if hf#=ERROR then "ファイルがありません", prints nl end

loop1:

buf, hf#, finputs f$=

if f$=EOF goto exit1

buf, ss, strstr p#=

if p#<>NULL then line#, printd "行目: ", prints buf, prints nl

line#, 1, + line#=

goto loop1

exit1:

hf#, close

end

About

本プログラムはLinux上で動作する独自仕様のコンパイラです、asm_x64やARM CPUのアセンブラソースコードを出力します。

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published