a21_txt02_2
をテンプレートにして作成
[
トップ
] [
新規
|
一覧
|
単語検索
|
最終更新
|
ヘルプ
]
開始行:
* 「10日くらいでできる!プログラミング言語自作入門」の続...
-(by [[K]], 2021.04.14)
** (1) HL-12
-JITコンパイラ化は高速化のためにやっているのですから、や...
(前略)
unsigned char *ic, *icq; // ic[]:内部コード、icq:ic[]へ...
unsigned char *dump0, *dump1; // codedumpのための変数(HL...
int jmps[10000], jp; // ジャンプ命令の場所を記憶しておく...
void putIc(int op, IntP p0, IntP p1, IntP p2, IntP p3) →...
int getHex(int c) → HL-11と同じなので省略
int get32(unsigned char *p) → HL-11と同じなので省略
void put32(unsigned char *p, int i) → HL-11と同じなので...
void putIcX86_sub(String s, IntP a[])
{
int i, j, k;
for (i = 0; s[i] != 0; ) {
if (s[i] == ' ' || s[i] == '\t' || s[i] == '_' |...
i++;
} else if (getHex(s[i]) >= 0 && getHex(s[i + 1])...
(中略)
} else if (s[i] == '%') {
(中略)
if (s[i + 2] == 'r') { // relative.
put32(icq, (int) a[j] - (int) (icq + 4));
icq += 4;
}
+ if (s[i + 2] == 'l') { // label.
+ put32(icq, (int) a[j]);
+ jmps[jp] = icq - ic; // ジャンプ命令のラ...
+ jp++;
+ icq += 4;
+ }
i += 3;
} else {
printf("putIcX86: error: '%s'\n", s);
exit(1);
}
}
}
void putIcX86(String s, IntP p0, IntP p1, IntP p2, IntP ...
////////////////////////////////////////////////////////...
(中略)
////////////////////////////////////////////////////////...
void sub_print(int i)
{
printf("%d\n", i);
}
clock_t t0; [この行追加]
void sub_time() [この関数追加]
{
printf("time: %.3f[sec]\n", (clock() - t0) / (double...
}
////////////////////////////////////////////////////////...
(中略)
////////////////////////////////////////////////////////...
(中略)
int tmpLabelAlloc() → HL-8と同じなので省略
void defLabel(int i) [この関数追加]
{
var[i] = icq - ic;
}
#define BInfSiz 10
int binf[BInfSiz * 100], bd, lbd; // binf:block-info, bd...
(中略)
////////////////////////////////////////////////////////...
int compile(String s)
{
int pc, pc1, i, j;
unsigned char *icq1, *icp;
pc1 = lexer(s, tc);
tc[pc1++] = TcSemi; // 末尾に「;」を付け忘れることが...
tc[pc1] = tc[pc1 + 1] = tc[pc1 + 2] = tc[pc1 + 3] = ...
icq = ic;
+ jp = 0;
putIcX86("60; 83_ec_7c;", 0, 0, 0, 0); // PUSHAD(); ...
(中略)
} else if (phrCmp(10, "!!*0 = !!*1 + 1; if (!!*2...
! putIcX86("8b_%1m0; 40; 89_%1m0; 3b_%2m0; 0f_...
(中略)
} else if (phrCmp( 0, "!!*0:", pc)) { // ラベル...
! defLabel(tc[wpc[0]]); // ラベルに対応するicq...
(中略)
! } else if (phrCmpPutIcX86( 7, "time;", pc, 0, 0,...
(中略)
putIcX86("83_c4_7c; 61; c3;", 0, 0, 0, 0); // ADD(ES...
icq1 = icq;
+ for (i = 0; i < jp; i++) { // ジャンプ命令の最適化.
+ icq = jmps[i] + ic; // icq=飛び先のラベル番号を...
+ j = *(IntP) get32(icq); // ラベル番号を取得.
+ icp = j + ic; // icp=飛び先の命令列の先頭.
+ while (*icp == 0xe9) { // 飛び先がジャンプ命令...
+ put32(icq, get32(icp + 1)); // 飛び先のラベ...
+ j = *(IntP) get32(icp + 1);
+ icp = j + ic;
+ }
+ }
+ for (i = 0; i < jp; i++) { // ジャンプ先の設定(相対...
+ icq = jmps[i] + ic;
+ j = *(IntP) get32(icq); // ラベル番号を取得.
+ icp = j + ic; // icp=飛び先の命令列の先頭.
+ put32(icq, icp - (icq + 4));
+ }
return icq1 - ic;
err:
printf("syntax error : %s %s %s %s\n", ts[tc[pc]], t...
return -1;
}
int run(String s)
{
if (compile(s) < 0)
return 1;
void (*func)() = (void (*)()) ic;
+ t0 = clock();
func();
return 0;
}
(後略)
-プログラムは745行になりました。これで毎度の以下のプログ...
i = 0;
label:
i = i + 1;
if (i < 100000000) goto label;
time;
-さっそく実行してみましょう。・・・あれ?HL-9aと比べて、...
|[[a21_txt01_3]]|HL-3|148行|RIGHT:7.0KB|条件分岐などをサ...
|[[a21_txt01_5]]|HL-5|214行|RIGHT:7.5KB|少し高速化|RIGHT:...
|[[a21_txt01_6]]|HL-6|284行|RIGHT:8.0KB|もっと高速化(が...
|[[a21_txt01_6a]]|HL-6a|297行|RIGHT:8.5KB|さらに高速化!...
|[[a21_txt01_9a]]|HL-9a|772行|RIGHT:20.0KB|C言語っぽく改...
|[[a21_txt02_2]]|HL-12|RIGHT:745行|RIGHT:16.0KB|ループ速...
** (2) なぜ速くならなかったのか?
-理由は、つまり、もとのHL-9aが速すぎたんです。JITコンパイ...
-しかし、そうだとしても、この結果はあまりにさみしいです。...
-そもそもJITコンパイラは機械語を生成して実行しているわけ...
-そしてなにより私はHL-12がどうも信じられません。だって挙...
-疑いを持つのはいいことです。では、次回のHL-12aでは、これ...
** (3) プログラムの説明
-主な改造ポイント
-[1] putIcX86()が %l を受け付けられるようにしました。
--これは、 %l を書くとそこにラベルと同名の変数のポインタ...
--なぜそんなことをするのかというと、飛び先のアドレスが決...
--最初にひとまず仮の値を書いておいて、あとで本来の値を計...
-[2] defLabel()関数を作りました。
--現状でやっていることは「var[i] = icq - ic;」だけなので...
-[3] compile()にジャンプ命令の最適化を入れました。
--これはHL-8で導入した、ジャンプ先がgoto命令だったらそこ...
--とはいえ、現状ではプログラムは命令e9を生成することはあ...
** 次回に続く
-次回: [[a21_txt02_2a]]
*こめんと欄
#comment
終了行:
* 「10日くらいでできる!プログラミング言語自作入門」の続...
-(by [[K]], 2021.04.14)
** (1) HL-12
-JITコンパイラ化は高速化のためにやっているのですから、や...
(前略)
unsigned char *ic, *icq; // ic[]:内部コード、icq:ic[]へ...
unsigned char *dump0, *dump1; // codedumpのための変数(HL...
int jmps[10000], jp; // ジャンプ命令の場所を記憶しておく...
void putIc(int op, IntP p0, IntP p1, IntP p2, IntP p3) →...
int getHex(int c) → HL-11と同じなので省略
int get32(unsigned char *p) → HL-11と同じなので省略
void put32(unsigned char *p, int i) → HL-11と同じなので...
void putIcX86_sub(String s, IntP a[])
{
int i, j, k;
for (i = 0; s[i] != 0; ) {
if (s[i] == ' ' || s[i] == '\t' || s[i] == '_' |...
i++;
} else if (getHex(s[i]) >= 0 && getHex(s[i + 1])...
(中略)
} else if (s[i] == '%') {
(中略)
if (s[i + 2] == 'r') { // relative.
put32(icq, (int) a[j] - (int) (icq + 4));
icq += 4;
}
+ if (s[i + 2] == 'l') { // label.
+ put32(icq, (int) a[j]);
+ jmps[jp] = icq - ic; // ジャンプ命令のラ...
+ jp++;
+ icq += 4;
+ }
i += 3;
} else {
printf("putIcX86: error: '%s'\n", s);
exit(1);
}
}
}
void putIcX86(String s, IntP p0, IntP p1, IntP p2, IntP ...
////////////////////////////////////////////////////////...
(中略)
////////////////////////////////////////////////////////...
void sub_print(int i)
{
printf("%d\n", i);
}
clock_t t0; [この行追加]
void sub_time() [この関数追加]
{
printf("time: %.3f[sec]\n", (clock() - t0) / (double...
}
////////////////////////////////////////////////////////...
(中略)
////////////////////////////////////////////////////////...
(中略)
int tmpLabelAlloc() → HL-8と同じなので省略
void defLabel(int i) [この関数追加]
{
var[i] = icq - ic;
}
#define BInfSiz 10
int binf[BInfSiz * 100], bd, lbd; // binf:block-info, bd...
(中略)
////////////////////////////////////////////////////////...
int compile(String s)
{
int pc, pc1, i, j;
unsigned char *icq1, *icp;
pc1 = lexer(s, tc);
tc[pc1++] = TcSemi; // 末尾に「;」を付け忘れることが...
tc[pc1] = tc[pc1 + 1] = tc[pc1 + 2] = tc[pc1 + 3] = ...
icq = ic;
+ jp = 0;
putIcX86("60; 83_ec_7c;", 0, 0, 0, 0); // PUSHAD(); ...
(中略)
} else if (phrCmp(10, "!!*0 = !!*1 + 1; if (!!*2...
! putIcX86("8b_%1m0; 40; 89_%1m0; 3b_%2m0; 0f_...
(中略)
} else if (phrCmp( 0, "!!*0:", pc)) { // ラベル...
! defLabel(tc[wpc[0]]); // ラベルに対応するicq...
(中略)
! } else if (phrCmpPutIcX86( 7, "time;", pc, 0, 0,...
(中略)
putIcX86("83_c4_7c; 61; c3;", 0, 0, 0, 0); // ADD(ES...
icq1 = icq;
+ for (i = 0; i < jp; i++) { // ジャンプ命令の最適化.
+ icq = jmps[i] + ic; // icq=飛び先のラベル番号を...
+ j = *(IntP) get32(icq); // ラベル番号を取得.
+ icp = j + ic; // icp=飛び先の命令列の先頭.
+ while (*icp == 0xe9) { // 飛び先がジャンプ命令...
+ put32(icq, get32(icp + 1)); // 飛び先のラベ...
+ j = *(IntP) get32(icp + 1);
+ icp = j + ic;
+ }
+ }
+ for (i = 0; i < jp; i++) { // ジャンプ先の設定(相対...
+ icq = jmps[i] + ic;
+ j = *(IntP) get32(icq); // ラベル番号を取得.
+ icp = j + ic; // icp=飛び先の命令列の先頭.
+ put32(icq, icp - (icq + 4));
+ }
return icq1 - ic;
err:
printf("syntax error : %s %s %s %s\n", ts[tc[pc]], t...
return -1;
}
int run(String s)
{
if (compile(s) < 0)
return 1;
void (*func)() = (void (*)()) ic;
+ t0 = clock();
func();
return 0;
}
(後略)
-プログラムは745行になりました。これで毎度の以下のプログ...
i = 0;
label:
i = i + 1;
if (i < 100000000) goto label;
time;
-さっそく実行してみましょう。・・・あれ?HL-9aと比べて、...
|[[a21_txt01_3]]|HL-3|148行|RIGHT:7.0KB|条件分岐などをサ...
|[[a21_txt01_5]]|HL-5|214行|RIGHT:7.5KB|少し高速化|RIGHT:...
|[[a21_txt01_6]]|HL-6|284行|RIGHT:8.0KB|もっと高速化(が...
|[[a21_txt01_6a]]|HL-6a|297行|RIGHT:8.5KB|さらに高速化!...
|[[a21_txt01_9a]]|HL-9a|772行|RIGHT:20.0KB|C言語っぽく改...
|[[a21_txt02_2]]|HL-12|RIGHT:745行|RIGHT:16.0KB|ループ速...
** (2) なぜ速くならなかったのか?
-理由は、つまり、もとのHL-9aが速すぎたんです。JITコンパイ...
-しかし、そうだとしても、この結果はあまりにさみしいです。...
-そもそもJITコンパイラは機械語を生成して実行しているわけ...
-そしてなにより私はHL-12がどうも信じられません。だって挙...
-疑いを持つのはいいことです。では、次回のHL-12aでは、これ...
** (3) プログラムの説明
-主な改造ポイント
-[1] putIcX86()が %l を受け付けられるようにしました。
--これは、 %l を書くとそこにラベルと同名の変数のポインタ...
--なぜそんなことをするのかというと、飛び先のアドレスが決...
--最初にひとまず仮の値を書いておいて、あとで本来の値を計...
-[2] defLabel()関数を作りました。
--現状でやっていることは「var[i] = icq - ic;」だけなので...
-[3] compile()にジャンプ命令の最適化を入れました。
--これはHL-8で導入した、ジャンプ先がgoto命令だったらそこ...
--とはいえ、現状ではプログラムは命令e9を生成することはあ...
** 次回に続く
-次回: [[a21_txt02_2a]]
*こめんと欄
#comment
ページ名: