「10日くらいでできる!プログラミング言語自作入門」の続編#1-2a
(1) HL-12a
- 今回のテーマは、本当にちゃんとコード生成できているのかの確認、どこまで速くできそうかをちょっと確認、の2つです。
(前略)
int phrCmpPutIcX86(int pid, String phr, int pc, int *pi, int lenExpr, void *sub, int *err) → HL-11と同じなので省略
int codedump; [この行追加]
///////////////////////////////////////////////////////////////////////////////
int compile(String s)
{
(中略)
jp = 0;
putIcX86("60; 83_ec_7c;", 0, 0, 0, 0); // PUSHAD(); SUB(ESP,124);
+ dump0 = icq;
for (i = 0; i < 10; i++) {
tmp_flag[i] = 0;
}
tmpLabelNo = 0;
bd = lbd = 0;
for (pc = 0; pc < pc1; ) { // コンパイル開始.
(中略)
+ } else if (phrCmp(35, "code", pc)) {
+ for (pc++; tc[pc] != TcSemi; pc++) {
+ if (tc[pc] == TcComma) continue;
+ *icq = var[tc[pc]];
+ icq++;
+ }
+ ppc1 = pc + 1;
+ } else if (phrCmp(36, "codedump !!*0;", pc)) {
+ codedump = var[tc[wpc[0]]];
} else if (phrCmp( 8, "!!***0;", pc)) { // これはかなりマッチしやすいので最後にする.
e0 = expr(0);
} else
goto err;
tmpFree(e0);
tmpFree(e2);
if (e0 < 0 || e2 < 0) goto err;
pc = ppc1;
}
if (bd > 0) {
printf("block nesting error (bd=%d, lbd=%d, pc=%d, pc1=%d\n", bd, lbd, pc, pc1);
return -1;
}
+ dump1 = icq;
putIcX86("83_c4_7c; 61; c3;", 0, 0, 0, 0); // ADD(ESP,124); POPAD(); RET();
icq1 = icq;
(中略)
}
int run(String s)
{
if (compile(s) < 0)
return 1;
+ if (codedump == 0) {
void (*func)() = (void (*)()) ic;
t0 = clock();
func();
+ } else {
+ int i, i1 = dump1 - dump0;
+ for (i = 0; i < i1; i++) {
+ printf("%02x ", dump0[i]);
+ }
+ printf("\n(len=%d)\n", i1);
+ }
return 0;
}
(後略)
- 2つめのcode命令は、かなり強烈な命令です。16進数を並べると、それをそのまま機械語生成に加えます。ちょっと間違えただけでプログラムが暴走します。
- 私はこの命令を使って、「こういう機械語にしたら何秒で実行できるかなあ」みたいなことを試します。
- どちらも具体的な例を、(2)や(3)で説明します。
(2) codedumpの結果を見てみる
>codedump 1
(len=0)
>run hl3.txt
8b 05 cc f9 41 00 89 05 d8 fa 41 00 8b 05 d8 fa
41 00 40 89 05 d8 fa 41 00 3b 05 e0 fa 41 00 0f
8c e7 ff ff ff e8 99 1c d9 ff
(len=42)
(3) code命令を使ってみる
- 私は最適化の方法を検討するとき、この例のようにcode命令をよく使います。だって、すごく簡単に試せますからね。
- また「CPUにはこういう命令があるらしい」みたいなときに試したくなることがありますが、そのときもcode命令を使います。
- 「アセンブラのソースコードを書いてアセンブルして実行する」と比べると、手軽さが全然違います!
次回に続く
こめんと欄