a21_txt02_4a
をテンプレートにして作成
[
トップ
] [
新規
|
一覧
|
単語検索
|
最終更新
|
ヘルプ
]
開始行:
* 「10日くらいでできる!プログラミング言語自作入門」の続...
-(by [[K]], 2021.04.21)
** (1) HL-14a
-HL-14は期待通りに速くなってくれて大変うれしいのですが、...
>regVar(0 i)
>codedump 1
(len=0)
>run hl3.txt
8b 05 0c 0a 42 00 89 c3 8b c3 40 89 c3 3b 05 28 0b 42 00...
(len=30)
-これは、1億回ループのプログラムをcodedump 1の状態でrunし...
8b 05 0c 0a 42 00; // EAX = 0;
89 c3; // EBX = EAX;
label:
8b c3; // EAX = EBX;
40; // EAX++;
89 c3; // EBX = EAX;
3b 05 28 0b 42 00; // if (EAX < 1億) goto label;
0f 8c ef ff ff ff;
e8 a9 22 f8 fd; // call time
-まあこれは、HL-14のアルゴリズムを考えれば、こうなって当...
-どこが低品質なのかというと、EBXレジスタを使っているにも...
-理想を考えると以下のようになります。
8b 1d 0c 0a 42 00; // EBX = 0;
label:
43; // EBX++;
3b 1d 28 0b 42 00; // if (EBX < 1億) goto label;
0f 8c ef ff ff ff;
e8 a9 22 f8 fd; // call time
-普通ならこのようにEBXをEBXのままで演算すべきなのです。こ...
----
-ここまでは、私もわかっていました。それこそ何年も前から分...
-でもようやく、これを簡単に書く方法を思いつきました。だか...
----
-HL-14の段階では、加算の二項演算子はこうなっています(opB...
8b_%1m0; 03_%2m0; 89_%0m0;
-これをHL-14aでは以下のようにします。
%1L0; 03_&8:%2m0; %0S;
-これの意味を説明します。
-まず最初の「%1L0;」ですが、これは基本的には「8b_%1m0;」...
-次に「&8:」という記述が新しいです。これはプリフィクス(...
-最後の「%0S;」は、もしr=0だったら、「89_%0m0;」と同じ動...
-では、%0と%1が同じ変数を指していて、しかもレジスタ変数だ...
-EBXなので、r=3になります。%1L0と%0Sは何も出力しません。...
03_%2m3;
-に相当する機械語だけが出てくることになるのです。おお、こ...
-もし%0と%1のどちらもレジスタ変数だけど、でも同じ変数では...
EBX = ESI + %2;
-みたいな状態だったら、いつも通りのEAX経由の計算になりま...
EAX = ESI;
EAX += %2;
EBX = EAX;
-これはまだだめじゃないかと思うかもしれません。まあその通...
----
-と思ったけど、これを書いて説明しているうちに何とかなりそ...
%1L02; 03_&8:%2m0; %0S;
-こう書かせることにします。それで、%1L02では%1と%0だけを...
--(1)%0と%1がレジスタ変数で、しかも同一変数であれば、%1L0...
--(2)上記以外で、%0がレジスタ変数であれば、%2が%0と等しい...
--(3)上記のどちらでもなければ、r=0として、従来通りEAX=%1;...
-これで余計なEAX経由の計算は最小限にできそうです!
// zx = xx + cx; に効いたらしい。
----
-[1]opBin[]を以下の記述に差し替え
String opBin[] = { // 二項演算子のための機械語.
! "%1L11; 3b_&8:%2m0; 0f_94_c0; 0f_b6_c0; 89_%0m0;", /...
! "%1L11; 3b_&8:%2m0; 0f_95_c0; 0f_b6_c0; 89_%0m0;", /...
! "%1L11; 3b_&8:%2m0; 0f_9c_c0; 0f_b6_c0; 89_%0m0;", /...
! "%1L11; 3b_&8:%2m0; 0f_9d_c0; 0f_b6_c0; 89_%0m0;", /...
! "%1L11; 3b_&8:%2m0; 0f_9e_c0; 0f_b6_c0; 89_%0m0;", /...
! "%1L11; 3b_&8:%2m0; 0f_9f_c0; 0f_b6_c0; 89_%0m0;", /...
! "%1L02; 03_&8:%2m0; %0S;", /...
! "%1L02; 2b_&8:%2m0; %0S;", /...
! "%1L02; 0f_af_&8:%2m0; %0S;", /...
"8b_%1m0; 99; f7_%2m7; 89_%0m0;", /...
"8b_%1m0; 99; f7_%2m7; 89_%0m2;", /...
! "%1L02; 23_&8:%2m0; %0S;", /...
! "%1L02; 8b_%2m1; d3_&1:f8; %0S;" /...
};
-[2]putIcX86_sub()関数に書き足し&変更
void putIcX86_sub(String s, IntP a[])
{
int i, j, k;
+ unsigned char addVal = 0, r = 0;
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])...
! *icq = getHex(s[i]) * 16 + getHex(s[i + 1]) ...
i += 2;
icq++;
+ addVal = 0;
+ } else if (s[i] == '&') {
+ addVal = r * (s[i + 1] - '0');
+ i += 2;
} else if (s[i] == '%') {
j = s[i + 1] - '0';
if (s[i + 2] == 'm') { // mod r/m.
k = s[i + 3] - '0';
+ i += 4;
+subcmd_m:
if (regVar(a[j]) < 0) {
! *icq = 0x05 + k * 8 + addVal;
put32(icq + 1, (int) a[j]);
icq += 5;
} else {
! *icq = 0xc0 + regVarNo[regVar(a[j])]...
icq++;
}
+ addVal = 0;
continue;
}
+ if (s[i + 2] == 'L') {
+ int l = s[i + 4] - '0';
+ k = s[i + 3] - '0';
+ i += 5;
+ if (regVar(a[j]) >= 0 && a[j] == a[k]) {
+ r = regVarNo[regVar(a[j])];
+ } else if (regVar(a[k]) >= 0 && a[k] != ...
+ k = r = regVarNo[regVar(a[k])];
+ *icq = 0x8b;
+ icq++;
+ goto subcmd_m;
+ } else {
+ k = r = 0; // EAX.;
+ *icq = 0x8b;
+ icq++;
+ goto subcmd_m;
+ }
+ continue;
+ }
+ if (s[i + 2] == 'S') {
+ if (r == 0) {
+ k = 0;
+ *icq = 0x89;
+ icq++;
+ i += 3;
+ goto subcmd_m;
+ }
+ }
if (s[i + 2] == 'i') { // int.
put32(icq, (int) a[j]);
icq += 4;
}
(中略)
} else {
printf("putIcX86: error: '%s'(%s)\n", s, &s[...
exit(1);
}
}
}
-[3]ifgoto()関数のうちの2行を差し替え
void ifgoto(int i, int not, int label)
{
int j = wpc[i];
if (j + 3 == wpc1[i] && TcEEq <= tc[j + 1] && tc[j +...
! putIcX86("%2L22; 3b_&8:%3m0; 0f_%0c_%1l;", (IntP...
} else {
i = expr(i);
! putIcX86("%2L22; 85_&9:c0; 0f_%0c_%1l;", (IntP) ...
tmpFree(i);
}
}
-[3]phrCmpPutIcX86()関数の一部を差し替え
for (i = 0; i < lenExpr; i++) {
! putIcX86("%0L00; 89_&8:44_24_%1c;", &var[e[i...
}
-[4]compile()関数の一部を差し替え(1)
if (phrCmp( 1, "!!*0 = !!*1;", pc)) { // 単純代入.
+ if (regVar(&var[tc[wpc[0]]]) < 0) {
! putIcX86("%1L11; 89_&8:%0m0;", &var[tc[w...
+ } else {
+ putIcX86("%0L00; 8b_&8:%1m0;", &var[tc[w...
+ }
} else if (phrCmp(10, "!!*0 = !!*1 + 1; if (!!*2...
! putIcX86("%1L11; &1:40; %1S; 3b_&8:%2m0; 0f_...
} else if (phrCmp( 9, "!!*0 = !!*1 + 1;", pc) &&...
! putIcX86("%0L00; &1:40; %0S;", &var[tc[wpc[0...
-[5]compile()関数の一部を差し替え(2)
} else if (phrCmp(15, "}", pc) && binf[bd] == Bl...
defLabel(binf[bd + ForCont]); // ラベルに対...
i = binf[bd + ForWpc01];
j = binf[bd + ForWpc02];
if (i + 3 == binf[bd + ForWpc11] && j + 2 ==...
// !!***1が「i < ?」かつ、!!***2が「i++...
! putIcX86("%1L11; &1:40; %1S; 3b_&8:%2m0;...
} else {
wpc [1] = binf[bd + ForWpc01];
wpc1[1] = binf[bd + ForWpc11];
wpc [2] = binf[bd + ForWpc02];
wpc1[2] = binf[bd + ForWpc12];
e2 = expr(2);
if (wpc[1] < wpc1[1]) { // !!***1に何ら...
ifgoto(1, 0, binf[bd + ForLopBgn]);
} else {
putIcX86("e9_%0l;", &var[binf[bd + F...
}
}
defLabel(binf[bd + ForBrk]); // ラベルに対応...
lbd = binf[bd+ ForLbd0]; // 以前の値を復元.
bd -= BInfSiz;
-[6]compile()関数に2行を追加
+ } else if (phrCmp(38, "!!*3 = mul64shr(!!*0, !!*...
+ putIcX86("8b_%0m0; f7_%1m5; 0f_ac_d0_%2c; 89...
----
-以上すべての改造を終えると、プログラムは906行になります。
** (2) プログラムの説明
-ここでプログラムの説明を書こうと思ったのですが、もう大体...
-だからもう些末なことしかのこっていないのですが、mul64shr...
-この特別処理を書くことによって、演算結果をいったん一時変...
** (3) 効果の確認
-まずはhl3.txtのコンパイル結果を確認してみます。
>regVar(0 i)
>codedump 1
(len=0)
>run hl3.txt
8b 1d 0c 0a 42 00 43 3b 1d 28 0b 42 00 0f 8c f3 ff ff ff...
(len=24)
-このコードを見やすい形で書き直すとこうなります。
8b 1d 0c 0a 42 00; // EBX = 0;
label:
43; // EBX++;
3b 1d 28 0b 42 00; // if (EBX < 1億) goto label;
0f 8c f3 ff ff ff:
e8 cc 23 f8 fd; // call time;
-おお、これはまさに上記の「理想形」です。とてもうまくいっ...
-肝心の実行速度も確認しました。
|ページ名|名前|行数|.exeの大きさ|説明|速度のめやす1|速度...
|[ [[a21_txt01]] ]|HL-1~HL-9a|RIGHT:49行~772行|RIGHT:6....
|[[a21_txt02]]|HL-11|RIGHT:692行|RIGHT:14.5KB|JITコンパイ...
|[[a21_txt02_1a]]|HL-11a|RIGHT:707行|RIGHT:15.0KB|簡単な...
|[[a21_txt02_2]]|HL-12|RIGHT:745行|RIGHT:16.0KB|ループ速...
|[[a21_txt02_2a]]|HL-12a|RIGHT:766行|RIGHT:16.5KB|codedum...
|[[a21_txt02_3]]|HL-13|RIGHT:827行|RIGHT:21.0KB|配列以外...
|[[a21_txt02_3a]]|HL-13a|RIGHT:819行|RIGHT:21.0KB|配列もJ...
|[[a21_txt02_4]]|HL-14|RIGHT:865行|RIGHT:21.5KB|レジスタ...
|[[a21_txt02_4a]]|HL-14a|RIGHT:906行|RIGHT:22.5KB|レジス...
** 次回に続く
-次回: [[a21_txt02_5]]
*こめんと欄
#comment
終了行:
* 「10日くらいでできる!プログラミング言語自作入門」の続...
-(by [[K]], 2021.04.21)
** (1) HL-14a
-HL-14は期待通りに速くなってくれて大変うれしいのですが、...
>regVar(0 i)
>codedump 1
(len=0)
>run hl3.txt
8b 05 0c 0a 42 00 89 c3 8b c3 40 89 c3 3b 05 28 0b 42 00...
(len=30)
-これは、1億回ループのプログラムをcodedump 1の状態でrunし...
8b 05 0c 0a 42 00; // EAX = 0;
89 c3; // EBX = EAX;
label:
8b c3; // EAX = EBX;
40; // EAX++;
89 c3; // EBX = EAX;
3b 05 28 0b 42 00; // if (EAX < 1億) goto label;
0f 8c ef ff ff ff;
e8 a9 22 f8 fd; // call time
-まあこれは、HL-14のアルゴリズムを考えれば、こうなって当...
-どこが低品質なのかというと、EBXレジスタを使っているにも...
-理想を考えると以下のようになります。
8b 1d 0c 0a 42 00; // EBX = 0;
label:
43; // EBX++;
3b 1d 28 0b 42 00; // if (EBX < 1億) goto label;
0f 8c ef ff ff ff;
e8 a9 22 f8 fd; // call time
-普通ならこのようにEBXをEBXのままで演算すべきなのです。こ...
----
-ここまでは、私もわかっていました。それこそ何年も前から分...
-でもようやく、これを簡単に書く方法を思いつきました。だか...
----
-HL-14の段階では、加算の二項演算子はこうなっています(opB...
8b_%1m0; 03_%2m0; 89_%0m0;
-これをHL-14aでは以下のようにします。
%1L0; 03_&8:%2m0; %0S;
-これの意味を説明します。
-まず最初の「%1L0;」ですが、これは基本的には「8b_%1m0;」...
-次に「&8:」という記述が新しいです。これはプリフィクス(...
-最後の「%0S;」は、もしr=0だったら、「89_%0m0;」と同じ動...
-では、%0と%1が同じ変数を指していて、しかもレジスタ変数だ...
-EBXなので、r=3になります。%1L0と%0Sは何も出力しません。...
03_%2m3;
-に相当する機械語だけが出てくることになるのです。おお、こ...
-もし%0と%1のどちらもレジスタ変数だけど、でも同じ変数では...
EBX = ESI + %2;
-みたいな状態だったら、いつも通りのEAX経由の計算になりま...
EAX = ESI;
EAX += %2;
EBX = EAX;
-これはまだだめじゃないかと思うかもしれません。まあその通...
----
-と思ったけど、これを書いて説明しているうちに何とかなりそ...
%1L02; 03_&8:%2m0; %0S;
-こう書かせることにします。それで、%1L02では%1と%0だけを...
--(1)%0と%1がレジスタ変数で、しかも同一変数であれば、%1L0...
--(2)上記以外で、%0がレジスタ変数であれば、%2が%0と等しい...
--(3)上記のどちらでもなければ、r=0として、従来通りEAX=%1;...
-これで余計なEAX経由の計算は最小限にできそうです!
// zx = xx + cx; に効いたらしい。
----
-[1]opBin[]を以下の記述に差し替え
String opBin[] = { // 二項演算子のための機械語.
! "%1L11; 3b_&8:%2m0; 0f_94_c0; 0f_b6_c0; 89_%0m0;", /...
! "%1L11; 3b_&8:%2m0; 0f_95_c0; 0f_b6_c0; 89_%0m0;", /...
! "%1L11; 3b_&8:%2m0; 0f_9c_c0; 0f_b6_c0; 89_%0m0;", /...
! "%1L11; 3b_&8:%2m0; 0f_9d_c0; 0f_b6_c0; 89_%0m0;", /...
! "%1L11; 3b_&8:%2m0; 0f_9e_c0; 0f_b6_c0; 89_%0m0;", /...
! "%1L11; 3b_&8:%2m0; 0f_9f_c0; 0f_b6_c0; 89_%0m0;", /...
! "%1L02; 03_&8:%2m0; %0S;", /...
! "%1L02; 2b_&8:%2m0; %0S;", /...
! "%1L02; 0f_af_&8:%2m0; %0S;", /...
"8b_%1m0; 99; f7_%2m7; 89_%0m0;", /...
"8b_%1m0; 99; f7_%2m7; 89_%0m2;", /...
! "%1L02; 23_&8:%2m0; %0S;", /...
! "%1L02; 8b_%2m1; d3_&1:f8; %0S;" /...
};
-[2]putIcX86_sub()関数に書き足し&変更
void putIcX86_sub(String s, IntP a[])
{
int i, j, k;
+ unsigned char addVal = 0, r = 0;
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])...
! *icq = getHex(s[i]) * 16 + getHex(s[i + 1]) ...
i += 2;
icq++;
+ addVal = 0;
+ } else if (s[i] == '&') {
+ addVal = r * (s[i + 1] - '0');
+ i += 2;
} else if (s[i] == '%') {
j = s[i + 1] - '0';
if (s[i + 2] == 'm') { // mod r/m.
k = s[i + 3] - '0';
+ i += 4;
+subcmd_m:
if (regVar(a[j]) < 0) {
! *icq = 0x05 + k * 8 + addVal;
put32(icq + 1, (int) a[j]);
icq += 5;
} else {
! *icq = 0xc0 + regVarNo[regVar(a[j])]...
icq++;
}
+ addVal = 0;
continue;
}
+ if (s[i + 2] == 'L') {
+ int l = s[i + 4] - '0';
+ k = s[i + 3] - '0';
+ i += 5;
+ if (regVar(a[j]) >= 0 && a[j] == a[k]) {
+ r = regVarNo[regVar(a[j])];
+ } else if (regVar(a[k]) >= 0 && a[k] != ...
+ k = r = regVarNo[regVar(a[k])];
+ *icq = 0x8b;
+ icq++;
+ goto subcmd_m;
+ } else {
+ k = r = 0; // EAX.;
+ *icq = 0x8b;
+ icq++;
+ goto subcmd_m;
+ }
+ continue;
+ }
+ if (s[i + 2] == 'S') {
+ if (r == 0) {
+ k = 0;
+ *icq = 0x89;
+ icq++;
+ i += 3;
+ goto subcmd_m;
+ }
+ }
if (s[i + 2] == 'i') { // int.
put32(icq, (int) a[j]);
icq += 4;
}
(中略)
} else {
printf("putIcX86: error: '%s'(%s)\n", s, &s[...
exit(1);
}
}
}
-[3]ifgoto()関数のうちの2行を差し替え
void ifgoto(int i, int not, int label)
{
int j = wpc[i];
if (j + 3 == wpc1[i] && TcEEq <= tc[j + 1] && tc[j +...
! putIcX86("%2L22; 3b_&8:%3m0; 0f_%0c_%1l;", (IntP...
} else {
i = expr(i);
! putIcX86("%2L22; 85_&9:c0; 0f_%0c_%1l;", (IntP) ...
tmpFree(i);
}
}
-[3]phrCmpPutIcX86()関数の一部を差し替え
for (i = 0; i < lenExpr; i++) {
! putIcX86("%0L00; 89_&8:44_24_%1c;", &var[e[i...
}
-[4]compile()関数の一部を差し替え(1)
if (phrCmp( 1, "!!*0 = !!*1;", pc)) { // 単純代入.
+ if (regVar(&var[tc[wpc[0]]]) < 0) {
! putIcX86("%1L11; 89_&8:%0m0;", &var[tc[w...
+ } else {
+ putIcX86("%0L00; 8b_&8:%1m0;", &var[tc[w...
+ }
} else if (phrCmp(10, "!!*0 = !!*1 + 1; if (!!*2...
! putIcX86("%1L11; &1:40; %1S; 3b_&8:%2m0; 0f_...
} else if (phrCmp( 9, "!!*0 = !!*1 + 1;", pc) &&...
! putIcX86("%0L00; &1:40; %0S;", &var[tc[wpc[0...
-[5]compile()関数の一部を差し替え(2)
} else if (phrCmp(15, "}", pc) && binf[bd] == Bl...
defLabel(binf[bd + ForCont]); // ラベルに対...
i = binf[bd + ForWpc01];
j = binf[bd + ForWpc02];
if (i + 3 == binf[bd + ForWpc11] && j + 2 ==...
// !!***1が「i < ?」かつ、!!***2が「i++...
! putIcX86("%1L11; &1:40; %1S; 3b_&8:%2m0;...
} else {
wpc [1] = binf[bd + ForWpc01];
wpc1[1] = binf[bd + ForWpc11];
wpc [2] = binf[bd + ForWpc02];
wpc1[2] = binf[bd + ForWpc12];
e2 = expr(2);
if (wpc[1] < wpc1[1]) { // !!***1に何ら...
ifgoto(1, 0, binf[bd + ForLopBgn]);
} else {
putIcX86("e9_%0l;", &var[binf[bd + F...
}
}
defLabel(binf[bd + ForBrk]); // ラベルに対応...
lbd = binf[bd+ ForLbd0]; // 以前の値を復元.
bd -= BInfSiz;
-[6]compile()関数に2行を追加
+ } else if (phrCmp(38, "!!*3 = mul64shr(!!*0, !!*...
+ putIcX86("8b_%0m0; f7_%1m5; 0f_ac_d0_%2c; 89...
----
-以上すべての改造を終えると、プログラムは906行になります。
** (2) プログラムの説明
-ここでプログラムの説明を書こうと思ったのですが、もう大体...
-だからもう些末なことしかのこっていないのですが、mul64shr...
-この特別処理を書くことによって、演算結果をいったん一時変...
** (3) 効果の確認
-まずはhl3.txtのコンパイル結果を確認してみます。
>regVar(0 i)
>codedump 1
(len=0)
>run hl3.txt
8b 1d 0c 0a 42 00 43 3b 1d 28 0b 42 00 0f 8c f3 ff ff ff...
(len=24)
-このコードを見やすい形で書き直すとこうなります。
8b 1d 0c 0a 42 00; // EBX = 0;
label:
43; // EBX++;
3b 1d 28 0b 42 00; // if (EBX < 1億) goto label;
0f 8c f3 ff ff ff:
e8 cc 23 f8 fd; // call time;
-おお、これはまさに上記の「理想形」です。とてもうまくいっ...
-肝心の実行速度も確認しました。
|ページ名|名前|行数|.exeの大きさ|説明|速度のめやす1|速度...
|[ [[a21_txt01]] ]|HL-1~HL-9a|RIGHT:49行~772行|RIGHT:6....
|[[a21_txt02]]|HL-11|RIGHT:692行|RIGHT:14.5KB|JITコンパイ...
|[[a21_txt02_1a]]|HL-11a|RIGHT:707行|RIGHT:15.0KB|簡単な...
|[[a21_txt02_2]]|HL-12|RIGHT:745行|RIGHT:16.0KB|ループ速...
|[[a21_txt02_2a]]|HL-12a|RIGHT:766行|RIGHT:16.5KB|codedum...
|[[a21_txt02_3]]|HL-13|RIGHT:827行|RIGHT:21.0KB|配列以外...
|[[a21_txt02_3a]]|HL-13a|RIGHT:819行|RIGHT:21.0KB|配列もJ...
|[[a21_txt02_4]]|HL-14|RIGHT:865行|RIGHT:21.5KB|レジスタ...
|[[a21_txt02_4a]]|HL-14a|RIGHT:906行|RIGHT:22.5KB|レジス...
** 次回に続く
-次回: [[a21_txt02_5]]
*こめんと欄
#comment
ページ名: