GMC-4コンパイラー
をテンプレートにして作成
[
トップ
] [
新規
|
一覧
|
単語検索
|
最終更新
|
ヘルプ
]
開始行:
[[FrontPage]]
2009/07/18 からのアクセス回数 &counter;
#contents
** GMC-4について [#ve7ca79f]
GMC-4は、学研の「大人の科学」Vol.24の付録に付いている4ビ...
http://otonanokagaku.net/magazine/vol24/index.html
&ref(GMC-4.jpg);
*** ハードウェア構成 [#qe5942f6]
GMC-4には、
- 1個の7セグメントLED
- 1個のスピーカ
- 7個のLED
- 数字キーとASET, INCR, RUN, RESETのキー
が載っており、
- プログラム領域は、00-4F
- メモリ領域は、50-5F
- A, B, Y, Z, A', B', Y', Z'の8個のレジスタ
を持っています。
- Aレジスタは、演算用レジスタ
- Yレジスタは、アドレスレジスタ
- Zレジスタは、条件レジスタ
として使用され、その他は、補助用のレジスタとなっています。
*** 命令セット [#tf2638b8]
GMC-4の命令セットは、
|命令コード|命令記号|実行フラグ|機能|
|0|KA|0,1|押している数字キーをArに入れる。押されていない...
|1|AO|1|Arの内容を数字LEDに点灯する。|
|2|CH|1|ArとBr、YrとZrの内容をそれぞれ入れ替える。|
|3|CY|1|ArとYrの内容を入れ替える。|
|4|AM|1|Arの内容をデータメモリに入れる。|
|5|MA|1|データメモリの内容をArに入れる。|
|6|M+|0,1|データメモリの内容にArの内容を加え、Arに入れる...
|7|M-|0,1|データメモリの内容からArの内容を引き、Arに入れ...
|8|TIA|1|命令の次のデータをArに入れる。|
|9|AIA|0,1|Arの内容に命令の次のデータを加え、Arに入れる。...
|A|TIY|1|命令の次のデータをYrに入れる。|
|B|AIY|0,1|Yrの内容に命令の次のデータを加え、Yrに入れる。...
|C|CIA|0,1|Arと命令の次のデータを比べる。異なる場合は実行...
|D|CIY|0,1|Yrと命令の次のデータを比べる。異なる場合は実行...
|F|JUMP|1|実行フラグが1のとき、続けて指定したアドレスにジ...
この他にサービスコールとして、
|命令コード|命令記号|実行フラグ|機能|
|E0|CAL RSTO|1|数字LEDを消灯する。|
|E1|CAL SETR|1|2進LEDを1個点灯する。点灯するLEDはYrで指定...
|E2|CAL RSTR|1|2進LEDを1個消灯する。消灯するLEDはYrで指定...
|E4|CAL CMPL|1|Arの内容をbit反転する。|
|E5|CAL CHNG|1|Ar、Br、Yr、Zrと補助レジスタA'r、B'r、Y'r...
|E6|CAL SIFT|0,1|Arの内容を1bit右へ移動する。結果が偶数の...
|E7|CAL ENDS|1|エンド音を鳴らす。|
|E8|CAL ERRS|1|エラー音を鳴らす。|
|E9|CAL SHTS|1|"ピッ"という音を鳴らす。|
|EA|CAL LONS|1|"ピー"という音を鳴らす。|
|EB|CAL SUND|1|Arの内容に対応する音階を鳴らす。|
|EC|CAL TIMR|1|(Arの内容+1)×0.1秒間プログラムの実行を停...
|ED|CAL DSPR|1|データメモリの内容を2進LEDに点灯する。5F番...
|EE|CAL DEM-|1|データメモリからArの内容を引き、10進数に直...
|EF|CAL DEM+|1|データメモリにArの内容を加え、10進数に直し...
があります。((E3のCAL INPTは、ありません))
** コンパイラー [#h5730b34]
GMC-4では、
- プログラムを命令セットで表現し
- 手でコードに翻訳
することで、プログラミングします。しかし、これではミスも...
そこで、以下のような簡易言語から命令セットに変換するコン...
例)15秒カウンタ
#pre{{
int a;
a = 15;
while (a > 0) {
out(a);
shts();
a = a - 1;
timer(10);
}
}}
生成された命令セット(アセンブラ)は、
#pre{{
TIA f
TIY 0
AM
L1: TIY 0
TIA 0
AIA 1
M-
JUMP L2
TIY 0
MA
AO
CAL SHTS
TIY 0
TIA 1
M-
TIY 0
AM
TIA a
CAL TIMR
JUMP L1
L2: CAL ENDS
L3: JUMP L3
}}
*** アセンブラ [#fbb36069]
命令セットからコードに翻訳するアセンブラが、以下のサイト...
http://www.musashinodenpa.com/misc/GMC4/
ここで変換すると
#pre{{
アドレス 命令 命令コード
00 TIA 8
01 <F> F
02 TIY A
03 <0> 0
04 AM 4
05 TIY A
06 <0> 0
07 TIA 8
08 <0> 0
09 AIA 9
0A <1> 1
0B M- 7
0C JUMP F
0D <0> 0
0E <2> 2
0F TIY A
10 <0> 0
11 MA 5
12 AO 1
13 CAL E
14 _SHTS 9
15 TIY A
16 <0> 0
17 TIA 8
18 <1> 1
19 M- 7
1A TIY A
1B <0> 0
1C AM 4
1D TIA 8
1E <A> A
1F CAL E
20 _TIMR C
21 JUMP F
22 <0> 0
23 <5> 5
24 CAL E
25 _ENDS 7
26 JUMP F
27 <2> 2
28 <6> 6
}}
ただし、最初のJUMP 02はバグのようで必ず最初のJUMPの値が正...
正しくは、JUMP 24です。
** シミュレータ [#i4366508]
GMC-4の元になった「FX-マイコン」のシミュレータが以下のURL...
http://homepage2.nifty.com/kocha_web/fxms/fxms.html
これを使って生成されたコードが正しく動作するか試してみま...
&ref(FX-Simulator.jpg);
- 例題をFX-マイコン・シミュレータで実行するためのファイル...
** 言語仕様 [#f7bba4b6]
言語は、命令セットの影響を強く受け、
- $A, $ZでAレジスターの値、Zレジスターの値をそのまま使う...
- 条件レジスタの制約がきつく、比較が>と==のみとなりました。
- 引き算は、変数に対してのみ可能です。
となりました。
コンパイラーの処理する言語仕様を以下に示します。
#pre{{
prog ::
declaration* statement+
declaration ::
int ID ( ',' ID )*
compoundStatement ::
'{' statement+ '}'
statement ::
expr ';'
| ID '=' expr;
| ';'
| compoundStatement
| ifStm
| whileStm
| 'led' '(' expr ')' ';'
| 'out' '(' expr ')' ';'
| 'cmpl' '(' expr ')' ';'
| 'shift' '(' expr ')' ';'
| 'shts' '(' expr ')' ';'
| 'sound' '(' expr ')' ';'
| 'timer' '(' expr ')' ';'
expr ::
'$A'
| 'key' '(' ')'
| term ( '+' CONST | '+' ID )*
| ID '-' CONST
| ID '-' ID
term ::
CONST | ID
ifStm ::
'if' '(' comparisonExpr ')' statement
whileStm ::
'while' '(' comparisonExpr ')' statement
comparisonExpr ::
'$Z'
| 'key' '(' ')'
| ID '>' CONST
| term '==' ( ID | CONST )
ID :: ('a'..'z'|'A'..'Z')('a'..'z'|'A'..'Z'|'0'..'9')*
CONST :: '0'..'9'+
}}
** コンパイラーの作成 [#mc05e0de]
コンパイラーは、ANTLRを使って作成しました。
構文のチェックやデバッグは、ANTLRWorksを使いました。
*** 字句解析 [#wc3b4229]
ANTLRでは、字句解析と構文解析が1つにまとまっているので、...
#pre{{
ID : ('a'..'z'|'A'..'Z')('a'..'z'|'A'..'Z'|'0'..'9')* ;
CONST : '0'..'9'+ ;
WS : (' '|'\t'|'\r'|'\n')+ {skip();} ;
}}
以下に構文解析の各処理について説明します。
*** 変数宣言 [#lf961fc9]
最初に、変数宣言での変数名の登録について説明します。
Main.javaに変数用のメソッドをいくつか定義しました。
#pre{{
static int symIndex = 0;
static Map symtable = new HashMap();
public static void addVar(String name) {
symtable.put(name, new Integer(symIndex++));
}
public static String varHexIndex(String name) {
Integer index = (Integer)symtable.get(name);
if (index == null) {
System.err.println("Invalid variable name");
}
return (String.format("%x", index.intValue()));
}
}}
これを使って変数宣言は、次のようになります。
#pre{{
declaration
: 'int' (i=ID)
{
Main.addVar($i.text);
}
( ',' (i=ID)
{
Main.addVar($i.text);
}
)* ';'
;
}}
宣言された変数をsymtableに登録するだけです。
*** 比較演算 [#m156c68c]
比較の結果はZレジスタに入り、Zレジスタが0の時に条件に一...
これは、JUMP命令がZレジスタが0の時だけ通過し、通過後Zレジ...
#pre{{
comparisonExpr
: '$Z'
| 'key' '(' ')'
{ System.out.println("KA"); }
|
(i=ID) '>' (c=CONST)
{
System.out.println("TIY\t" + Main.varHexIndex($i.tex...
System.out.println("TIA\t" + Main.toHexString($c.tex...
System.out.println("AIA\t1");
System.out.println("M-");
}
| term (
'==' (c=CONST)
{ System.out.println("CIA\t" + Main.toHexString($c.t...
| '==' (i=ID)
{ System.out.println("CIY\t" + Main.varHexIndex($i.te...
)
;
}}
- kye()関数の場合、KA命令を実行し、その結果のZレジスタの...
- >演算は、Aレジスタの値から(定数+1)を引いて判断します。
- ==演算は、CIA, CIYの比較命令を使います。
ここでは、プログラムが組める最低限の演算にとどめました。
*** 項 [#ad0ccb45]
演算はAレジスタに結果が入るようにしました。
項には、定数と変数が指定されますので、その値をAレジスタに...
#pre{{
term
: (c=CONST)
{ System.out.println("TIA\t" + Main.toHexString($c.text...
| (i=ID)
{
System.out.println("TIY\t" + Main.varHexIndex($i.text));
System.out.println("MA");
}
;
}}
*** 演算 [#e8361cf2]
演算処理には、足し算, 引き算, key(), $Aを使うことができま...
命令セットの制限が強いので、今回は引き算は、変数に対する...
$Aは、key()関数でセットされたAレジスタの値を使用するため...
演算の定義は、
#pre{{
expr
: '$A'
| term (
'+' (c=CONST)
{
System.out.println("AIA\t" + Main.toHexString($c.text));
}
| '+' (i=ID)
{
System.out.println("TIY\t" + Main.varHexIndex($i.text));
System.out.println("M+");
}
)*
| 'key' '(' ')'
{ System.out.println("KA"); }
| (i=ID) '-' (c=CONST)
{
System.out.println("TIY\t" + Main.varHexIndex($i.text));
System.out.println("TIA\t" + Main.toHexString($c.text));
System.out.println("M-");
}
| (a=ID) '-' (b=ID)
{
System.out.println("TIY\t" + Main.varHexIndex($b.text));
System.out.println("MA");
System.out.println("TIY\t" + Main.varHexIndex($a.text));
System.out.println("M-");
}
;
}}
*** 文 [#fd0a6864]
文では、代入文、複合文、if文、while文、関数呼び出しを定義...
#pre{{
statement
: expr ';'
| (i=ID) '=' expr ';'
{
System.out.println("TIY\t" + Main.varHexIndex($i.text));
System.out.println("AM");
}
| ';'
| compoundStatement
| ifStm
| whileStm
| 'led' '(' expr ')' ';'
{
System.out.println("TIY E");
System.out.println("AM");
System.out.println("CAL DSPR");
}
| 'out' '(' expr ')' ';'
{ System.out.println("AO"); }
| 'cmpl' '(' expr ')' ';'
{ System.out.println("CAL CMPL"); }
| 'shift' '(' expr ')' ';'
{ System.out.println("CAL SIFT"); }
| 'shts' '(' ')' ';'
{ System.out.println("CAL SHTS"); }
| 'sound' '(' expr ')' ';'
{ System.out.println("CAL SOUND"); }
| 'timer' '(' expr ')' ';'
{ System.out.println("CAL TIMR"); }
;
}}
*** 複合文 [#wec616ed]
複合文は、{と}で文を複数宣言することを定義するだけです。
#pre{{
compoundStatement
: '{' statement+ '}'
;
}}
*** if文 [#ye5a1710]
if文は、elseなしの簡単なものとしました。(今後の課題)
#pre{{
ifStm
@init {
String label = Main.genLabel();
}
@after {
System.out.print(label + ": ");
}
: 'if' '(' comparisonExpr ')'
{
System.out.println("JUMP\t" + label);
}
statement
;
}}
@initと@afterで囲まれた部分は、if文の最初と終わりに呼び出...
ここでは、JUMP先のラベルの生成とレベル付けを行っています。
if文の比較の後で、JUMP命令を入れるだけの簡単な構造にして...
*** while文 [#u9c134f6]
while文もbreak, continueなしの簡単なものにしています。
if文と同様に@init, @afterでラベルの生成とJUMP, 終了ラベル...
#pre{{
whileStm
@init {
String label1 = Main.genLabel();
String label2 = Main.genLabel();
}
@after {
System.out.println("JUMP\t" + label1);
System.out.print(label2 + ": ");
}
: 'while'
{ System.out.print(label1 + ": "); }
'(' comparisonExpr ')'
{ System.out.println("JUMP\t" + label2); }
statement
;
}}
*** プログラム全体 [#ob1df828]
プログラム全体は、変数宣言と文のならびと定義し、終了した...
#pre{{
prog
: declaration*
(
statement
)+
{
String label = Main.genLabel();
System.out.println("CAL ENDS");
System.out.println(label + ": JUMP\t" + label);
}
;
}}
これだけの処理で、コンパイラーができるのです。ANTLRを使う...
** ソース [#u66b7263]
GMC-4コンパイラーのEclipseプロジェクトを以下のファイルを...
- &ref(Gem4c.zip);
** コメント [#ia6995e1]
この記事は、
#vote(おもしろかった[48],そうでもない[1],わかりずらい[0])
皆様のご意見、ご希望をお待ちしております。
- コンパイラーの作成を追加しました。 -- [[竹本 浩]] &new...
- 始めまして。「学研 大人の科学マガジン Vol.24 4ビットマ...
- ソフト屋 巣さま、ありがとうございます。 -- [[竹本 浩]...
- ArduinoでGMC-4を作ってみました。[[Arduino勉強会/0E-GMC4...
#comment_kcaptcha
終了行:
[[FrontPage]]
2009/07/18 からのアクセス回数 &counter;
#contents
** GMC-4について [#ve7ca79f]
GMC-4は、学研の「大人の科学」Vol.24の付録に付いている4ビ...
http://otonanokagaku.net/magazine/vol24/index.html
&ref(GMC-4.jpg);
*** ハードウェア構成 [#qe5942f6]
GMC-4には、
- 1個の7セグメントLED
- 1個のスピーカ
- 7個のLED
- 数字キーとASET, INCR, RUN, RESETのキー
が載っており、
- プログラム領域は、00-4F
- メモリ領域は、50-5F
- A, B, Y, Z, A', B', Y', Z'の8個のレジスタ
を持っています。
- Aレジスタは、演算用レジスタ
- Yレジスタは、アドレスレジスタ
- Zレジスタは、条件レジスタ
として使用され、その他は、補助用のレジスタとなっています。
*** 命令セット [#tf2638b8]
GMC-4の命令セットは、
|命令コード|命令記号|実行フラグ|機能|
|0|KA|0,1|押している数字キーをArに入れる。押されていない...
|1|AO|1|Arの内容を数字LEDに点灯する。|
|2|CH|1|ArとBr、YrとZrの内容をそれぞれ入れ替える。|
|3|CY|1|ArとYrの内容を入れ替える。|
|4|AM|1|Arの内容をデータメモリに入れる。|
|5|MA|1|データメモリの内容をArに入れる。|
|6|M+|0,1|データメモリの内容にArの内容を加え、Arに入れる...
|7|M-|0,1|データメモリの内容からArの内容を引き、Arに入れ...
|8|TIA|1|命令の次のデータをArに入れる。|
|9|AIA|0,1|Arの内容に命令の次のデータを加え、Arに入れる。...
|A|TIY|1|命令の次のデータをYrに入れる。|
|B|AIY|0,1|Yrの内容に命令の次のデータを加え、Yrに入れる。...
|C|CIA|0,1|Arと命令の次のデータを比べる。異なる場合は実行...
|D|CIY|0,1|Yrと命令の次のデータを比べる。異なる場合は実行...
|F|JUMP|1|実行フラグが1のとき、続けて指定したアドレスにジ...
この他にサービスコールとして、
|命令コード|命令記号|実行フラグ|機能|
|E0|CAL RSTO|1|数字LEDを消灯する。|
|E1|CAL SETR|1|2進LEDを1個点灯する。点灯するLEDはYrで指定...
|E2|CAL RSTR|1|2進LEDを1個消灯する。消灯するLEDはYrで指定...
|E4|CAL CMPL|1|Arの内容をbit反転する。|
|E5|CAL CHNG|1|Ar、Br、Yr、Zrと補助レジスタA'r、B'r、Y'r...
|E6|CAL SIFT|0,1|Arの内容を1bit右へ移動する。結果が偶数の...
|E7|CAL ENDS|1|エンド音を鳴らす。|
|E8|CAL ERRS|1|エラー音を鳴らす。|
|E9|CAL SHTS|1|"ピッ"という音を鳴らす。|
|EA|CAL LONS|1|"ピー"という音を鳴らす。|
|EB|CAL SUND|1|Arの内容に対応する音階を鳴らす。|
|EC|CAL TIMR|1|(Arの内容+1)×0.1秒間プログラムの実行を停...
|ED|CAL DSPR|1|データメモリの内容を2進LEDに点灯する。5F番...
|EE|CAL DEM-|1|データメモリからArの内容を引き、10進数に直...
|EF|CAL DEM+|1|データメモリにArの内容を加え、10進数に直し...
があります。((E3のCAL INPTは、ありません))
** コンパイラー [#h5730b34]
GMC-4では、
- プログラムを命令セットで表現し
- 手でコードに翻訳
することで、プログラミングします。しかし、これではミスも...
そこで、以下のような簡易言語から命令セットに変換するコン...
例)15秒カウンタ
#pre{{
int a;
a = 15;
while (a > 0) {
out(a);
shts();
a = a - 1;
timer(10);
}
}}
生成された命令セット(アセンブラ)は、
#pre{{
TIA f
TIY 0
AM
L1: TIY 0
TIA 0
AIA 1
M-
JUMP L2
TIY 0
MA
AO
CAL SHTS
TIY 0
TIA 1
M-
TIY 0
AM
TIA a
CAL TIMR
JUMP L1
L2: CAL ENDS
L3: JUMP L3
}}
*** アセンブラ [#fbb36069]
命令セットからコードに翻訳するアセンブラが、以下のサイト...
http://www.musashinodenpa.com/misc/GMC4/
ここで変換すると
#pre{{
アドレス 命令 命令コード
00 TIA 8
01 <F> F
02 TIY A
03 <0> 0
04 AM 4
05 TIY A
06 <0> 0
07 TIA 8
08 <0> 0
09 AIA 9
0A <1> 1
0B M- 7
0C JUMP F
0D <0> 0
0E <2> 2
0F TIY A
10 <0> 0
11 MA 5
12 AO 1
13 CAL E
14 _SHTS 9
15 TIY A
16 <0> 0
17 TIA 8
18 <1> 1
19 M- 7
1A TIY A
1B <0> 0
1C AM 4
1D TIA 8
1E <A> A
1F CAL E
20 _TIMR C
21 JUMP F
22 <0> 0
23 <5> 5
24 CAL E
25 _ENDS 7
26 JUMP F
27 <2> 2
28 <6> 6
}}
ただし、最初のJUMP 02はバグのようで必ず最初のJUMPの値が正...
正しくは、JUMP 24です。
** シミュレータ [#i4366508]
GMC-4の元になった「FX-マイコン」のシミュレータが以下のURL...
http://homepage2.nifty.com/kocha_web/fxms/fxms.html
これを使って生成されたコードが正しく動作するか試してみま...
&ref(FX-Simulator.jpg);
- 例題をFX-マイコン・シミュレータで実行するためのファイル...
** 言語仕様 [#f7bba4b6]
言語は、命令セットの影響を強く受け、
- $A, $ZでAレジスターの値、Zレジスターの値をそのまま使う...
- 条件レジスタの制約がきつく、比較が>と==のみとなりました。
- 引き算は、変数に対してのみ可能です。
となりました。
コンパイラーの処理する言語仕様を以下に示します。
#pre{{
prog ::
declaration* statement+
declaration ::
int ID ( ',' ID )*
compoundStatement ::
'{' statement+ '}'
statement ::
expr ';'
| ID '=' expr;
| ';'
| compoundStatement
| ifStm
| whileStm
| 'led' '(' expr ')' ';'
| 'out' '(' expr ')' ';'
| 'cmpl' '(' expr ')' ';'
| 'shift' '(' expr ')' ';'
| 'shts' '(' expr ')' ';'
| 'sound' '(' expr ')' ';'
| 'timer' '(' expr ')' ';'
expr ::
'$A'
| 'key' '(' ')'
| term ( '+' CONST | '+' ID )*
| ID '-' CONST
| ID '-' ID
term ::
CONST | ID
ifStm ::
'if' '(' comparisonExpr ')' statement
whileStm ::
'while' '(' comparisonExpr ')' statement
comparisonExpr ::
'$Z'
| 'key' '(' ')'
| ID '>' CONST
| term '==' ( ID | CONST )
ID :: ('a'..'z'|'A'..'Z')('a'..'z'|'A'..'Z'|'0'..'9')*
CONST :: '0'..'9'+
}}
** コンパイラーの作成 [#mc05e0de]
コンパイラーは、ANTLRを使って作成しました。
構文のチェックやデバッグは、ANTLRWorksを使いました。
*** 字句解析 [#wc3b4229]
ANTLRでは、字句解析と構文解析が1つにまとまっているので、...
#pre{{
ID : ('a'..'z'|'A'..'Z')('a'..'z'|'A'..'Z'|'0'..'9')* ;
CONST : '0'..'9'+ ;
WS : (' '|'\t'|'\r'|'\n')+ {skip();} ;
}}
以下に構文解析の各処理について説明します。
*** 変数宣言 [#lf961fc9]
最初に、変数宣言での変数名の登録について説明します。
Main.javaに変数用のメソッドをいくつか定義しました。
#pre{{
static int symIndex = 0;
static Map symtable = new HashMap();
public static void addVar(String name) {
symtable.put(name, new Integer(symIndex++));
}
public static String varHexIndex(String name) {
Integer index = (Integer)symtable.get(name);
if (index == null) {
System.err.println("Invalid variable name");
}
return (String.format("%x", index.intValue()));
}
}}
これを使って変数宣言は、次のようになります。
#pre{{
declaration
: 'int' (i=ID)
{
Main.addVar($i.text);
}
( ',' (i=ID)
{
Main.addVar($i.text);
}
)* ';'
;
}}
宣言された変数をsymtableに登録するだけです。
*** 比較演算 [#m156c68c]
比較の結果はZレジスタに入り、Zレジスタが0の時に条件に一...
これは、JUMP命令がZレジスタが0の時だけ通過し、通過後Zレジ...
#pre{{
comparisonExpr
: '$Z'
| 'key' '(' ')'
{ System.out.println("KA"); }
|
(i=ID) '>' (c=CONST)
{
System.out.println("TIY\t" + Main.varHexIndex($i.tex...
System.out.println("TIA\t" + Main.toHexString($c.tex...
System.out.println("AIA\t1");
System.out.println("M-");
}
| term (
'==' (c=CONST)
{ System.out.println("CIA\t" + Main.toHexString($c.t...
| '==' (i=ID)
{ System.out.println("CIY\t" + Main.varHexIndex($i.te...
)
;
}}
- kye()関数の場合、KA命令を実行し、その結果のZレジスタの...
- >演算は、Aレジスタの値から(定数+1)を引いて判断します。
- ==演算は、CIA, CIYの比較命令を使います。
ここでは、プログラムが組める最低限の演算にとどめました。
*** 項 [#ad0ccb45]
演算はAレジスタに結果が入るようにしました。
項には、定数と変数が指定されますので、その値をAレジスタに...
#pre{{
term
: (c=CONST)
{ System.out.println("TIA\t" + Main.toHexString($c.text...
| (i=ID)
{
System.out.println("TIY\t" + Main.varHexIndex($i.text));
System.out.println("MA");
}
;
}}
*** 演算 [#e8361cf2]
演算処理には、足し算, 引き算, key(), $Aを使うことができま...
命令セットの制限が強いので、今回は引き算は、変数に対する...
$Aは、key()関数でセットされたAレジスタの値を使用するため...
演算の定義は、
#pre{{
expr
: '$A'
| term (
'+' (c=CONST)
{
System.out.println("AIA\t" + Main.toHexString($c.text));
}
| '+' (i=ID)
{
System.out.println("TIY\t" + Main.varHexIndex($i.text));
System.out.println("M+");
}
)*
| 'key' '(' ')'
{ System.out.println("KA"); }
| (i=ID) '-' (c=CONST)
{
System.out.println("TIY\t" + Main.varHexIndex($i.text));
System.out.println("TIA\t" + Main.toHexString($c.text));
System.out.println("M-");
}
| (a=ID) '-' (b=ID)
{
System.out.println("TIY\t" + Main.varHexIndex($b.text));
System.out.println("MA");
System.out.println("TIY\t" + Main.varHexIndex($a.text));
System.out.println("M-");
}
;
}}
*** 文 [#fd0a6864]
文では、代入文、複合文、if文、while文、関数呼び出しを定義...
#pre{{
statement
: expr ';'
| (i=ID) '=' expr ';'
{
System.out.println("TIY\t" + Main.varHexIndex($i.text));
System.out.println("AM");
}
| ';'
| compoundStatement
| ifStm
| whileStm
| 'led' '(' expr ')' ';'
{
System.out.println("TIY E");
System.out.println("AM");
System.out.println("CAL DSPR");
}
| 'out' '(' expr ')' ';'
{ System.out.println("AO"); }
| 'cmpl' '(' expr ')' ';'
{ System.out.println("CAL CMPL"); }
| 'shift' '(' expr ')' ';'
{ System.out.println("CAL SIFT"); }
| 'shts' '(' ')' ';'
{ System.out.println("CAL SHTS"); }
| 'sound' '(' expr ')' ';'
{ System.out.println("CAL SOUND"); }
| 'timer' '(' expr ')' ';'
{ System.out.println("CAL TIMR"); }
;
}}
*** 複合文 [#wec616ed]
複合文は、{と}で文を複数宣言することを定義するだけです。
#pre{{
compoundStatement
: '{' statement+ '}'
;
}}
*** if文 [#ye5a1710]
if文は、elseなしの簡単なものとしました。(今後の課題)
#pre{{
ifStm
@init {
String label = Main.genLabel();
}
@after {
System.out.print(label + ": ");
}
: 'if' '(' comparisonExpr ')'
{
System.out.println("JUMP\t" + label);
}
statement
;
}}
@initと@afterで囲まれた部分は、if文の最初と終わりに呼び出...
ここでは、JUMP先のラベルの生成とレベル付けを行っています。
if文の比較の後で、JUMP命令を入れるだけの簡単な構造にして...
*** while文 [#u9c134f6]
while文もbreak, continueなしの簡単なものにしています。
if文と同様に@init, @afterでラベルの生成とJUMP, 終了ラベル...
#pre{{
whileStm
@init {
String label1 = Main.genLabel();
String label2 = Main.genLabel();
}
@after {
System.out.println("JUMP\t" + label1);
System.out.print(label2 + ": ");
}
: 'while'
{ System.out.print(label1 + ": "); }
'(' comparisonExpr ')'
{ System.out.println("JUMP\t" + label2); }
statement
;
}}
*** プログラム全体 [#ob1df828]
プログラム全体は、変数宣言と文のならびと定義し、終了した...
#pre{{
prog
: declaration*
(
statement
)+
{
String label = Main.genLabel();
System.out.println("CAL ENDS");
System.out.println(label + ": JUMP\t" + label);
}
;
}}
これだけの処理で、コンパイラーができるのです。ANTLRを使う...
** ソース [#u66b7263]
GMC-4コンパイラーのEclipseプロジェクトを以下のファイルを...
- &ref(Gem4c.zip);
** コメント [#ia6995e1]
この記事は、
#vote(おもしろかった[48],そうでもない[1],わかりずらい[0])
皆様のご意見、ご希望をお待ちしております。
- コンパイラーの作成を追加しました。 -- [[竹本 浩]] &new...
- 始めまして。「学研 大人の科学マガジン Vol.24 4ビットマ...
- ソフト屋 巣さま、ありがとうございます。 -- [[竹本 浩]...
- ArduinoでGMC-4を作ってみました。[[Arduino勉強会/0E-GMC4...
#comment_kcaptcha
ページ名:
SmartDoc