a21_txt02_5
をテンプレートにして作成
[
トップ
] [
新規
|
一覧
|
単語検索
|
最終更新
|
ヘルプ
]
開始行:
* 「10日くらいでできる!プログラミング言語自作入門」の続...
-(by [[K]], 2021.04.22)
** (1) HL-15
-今回の最適化は、a = b + c - d; みたいな式に関するもので...
>codedump 1
(len=0)
>a=b+c-d
8b 05 58 0b 42 00 03 05 5c 0b 42 00 89 05 90 0a 42 00 8b...
(len=48)
-これを見やすくするとこうなっています。
8b 05 58 0b 42 00; // EAX = b;
03 05 5c 0b 42 00; // EAX += c;
89 05 90 0a 42 00; // _t0 = EAX;
8b 05 90 0a 42 00; // EAX = _t0;
2b 05 60 0b 42 00; // EAX -= d;
89 05 94 0a 42 00; // _t1 = EAX;
8b 05 94 0a 42 00; // EAX = _t1;
89 05 54 0b 42 00; // a = EAX;
-はい、これはひどいです。_t0や_t1に書いたり読み込んだり、...
-これに対して、理想形はこうなります。
8b 05 58 0b 42 00; // EAX = b;
03 05 5c 0b 42 00; // EAX += c;
2b 05 60 0b 42 00; // EAX -= d;
89 05 54 0b 42 00; // a = EAX;
-っていうか、普通こうなるべきですよね。
----
-もう一つ気になっているのは、このコンパイル結果です。
>if (a+b<c-d) { x=0; }
8b 05 54 0b 42 00; // EAX = a;
03 05 58 0b 42 00; // EAX += b;
89 05 90 0a 42 00; // _t0 = EAX;
8b 05 5c 0b 42 00; // EAX = c;
2b 05 60 0b 42 00; // EAX -= d;
89 05 94 0a 42 00; // _t1 = EAX;
8b 05 90 0a 42 00; // EAX = _t0;
3b 05 94 0a 42 00; // if (EAX < _t1) { EAX = 1: } (S...
0f 9c c0;
0f b6 c0;
89 05 98 0a 42 00; // _t2 = EAX;
8b 05 98 0a 42 00; // EAX = _t2;
85 c0; // if (EAX == 0) goto skip;
0f 84 0c 00 00 00;
8b 05 0c 0a 42 00; // EAX = 0;
89 05 64 0b 42 00; // x = EAX;
skip:
-これがだめだなあと思うのは、_t2への無駄な読み書きと、0f_...
8b 05 54 0b 42 00; // EAX = a;
03 05 58 0b 42 00; // EAX += b;
89 05 90 0a 42 00; // _t0 = EAX;
8b 05 5c 0b 42 00; // EAX = c;
2b 05 60 0b 42 00; // EAX -= d;
89 05 94 0a 42 00; // _t1 = EAX;
8b 05 90 0a 42 00; // EAX = _t0;
3b 05 94 0a 42 00; // if (EAX >= _t1) goto skip;
0f 8d 0c 00 00 00;
8b 05 0c 0a 42 00; // EAX = 0;
89 05 64 0b 42 00; // x = EAX;
skip:
----
-ということで、HL-15はこの2つの問題を解決しようと思います。
-[1]regVar()関数の後、putIcX86_sub()関数の前に以下を追加
unsigned char *icq0, *icq1, *icqSet;
void optimizerX86()
{
int i;
if (icq0 != icq) {
if (icq0[0] == 0x0f && 0x90 <= icq0[1] && icq0[1...
icqSet = icq0;
}
if (icq0[0] == 0x8b && icq1 != 0 && icq1[0] == 0...
icq = icq0; // 8b命令は削除.
i = (IntP) get32(icq1 + 2) - var;
if (TcTmp0 <= i && i <= TcTmp9) {
icq = icq1; // 89命令も削除.
}
}
icq1 = icq0;
icq0 = icq;
}
if (icqSet + 14 == icq && memcmp(&icqSet[2], "\xc0\x...
memcpy(&icqSet[2], &icqSet[10], 4);
icqSet[1] -= 0x10; // SETcc → Jcc.
if (icqSet[9] == 0x84) {
icqSet[1] ^= 1; // 条件反転.
}
icq0 = icq = icqSet + 6;
icq1 = icqSet = 0;
jmps[jp - 1] = icq - 4 - ic;
}
}
-[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 (s[i] == ';') {
+ i++;
+ optimizerX86();
} else if (getHex(s[i]) >= 0 && getHex(s[i + 1]) ...
(中略)
}
-[3]defLabel()関数に一行追加
void defLabel(int i)
{
var[i] = icq - ic;
+ icq1 = icqSet = 0;
}
-compile()関数を少し改造
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 = icq0 = ic;
jp = 0;
+ icq1 = icqSet = 0;
putIcX86("60; 83_ec_7c;", 0, 0, 0, 0); // PUSHAD(); ...
regVarSaveLoad(RvLoad);
dump0 = icq;
(中略)
}
----
-以上すべての改造を終えると、プログラムは942行になります。
-さて、うまく動くでしょうか。
>a=b+c-d
8b 05 30 0b 42 00 03 05 34 0b 42 00 2b 05 38 0b 42 00 89...
(len=24)
-うまくいっています。ちゃんと上記の理想通りになっています。
-if文のほうはどうでしょうか。
>if (a+b<c-d) { x=0; }
8b 05 2c 0b 42 00 03 05 30 0b 42 00 89 05 a0 0a 42 00 8b...
8b 05 a0 0a 42 00 3b 05 a4 0a 42 00 0f 9c c0 83 e0 01 85...
89 05 60 0b 42 00
(len=74)
-これもうまくいっています!
** (2) プログラムの説明
-今回の改造の中心は、optimizerX86()関数です。
-この関数は、putIcX86()でセミコロンが来たタイミングで呼ば...
-まず、3つのグローバル変数があります。
--icq0 : 直前のセミコロンの位置(=今の命令の開始位置)
--icq1 : さらにその前のセミコロンの位置(=1つ前の命令の...
--icqSet : SETcc命令を見つけたら、その先頭を記憶しておく
-icqとicq0とicq1を使えば、連続した2命令をチェックすること...
-またSETcc命令の後に最適化すべきパターンが来ていたら、前...
-最適化対象の機械語フレーズの中にラベルがあると、どこから...
** (3) 成果の比較
-上記みたいなのはすごく特別でレアケースなのか、それともよ...
-サイズが小さくなったからいいとか悪いとかではなく、「サイ...
||HL-13a|HL-14|HL-14a|HL-15|
|mandel.c|RIGHT:1087|RIGHT:1007|RIGHT:942|RIGHT:768|
|maze.c|RIGHT:2192|RIGHT:2192|RIGHT:2192|RIGHT:1770|
|kcube.c|RIGHT:4623|RIGHT:4623|RIGHT:4623|RIGHT:3695|
|invader.c|RIGHT:3260|RIGHT:3260|RIGHT:3260|RIGHT:2750|
** 次回に続く
-次回: [[a21_txt02_5a]]
*こめんと欄
#comment
終了行:
* 「10日くらいでできる!プログラミング言語自作入門」の続...
-(by [[K]], 2021.04.22)
** (1) HL-15
-今回の最適化は、a = b + c - d; みたいな式に関するもので...
>codedump 1
(len=0)
>a=b+c-d
8b 05 58 0b 42 00 03 05 5c 0b 42 00 89 05 90 0a 42 00 8b...
(len=48)
-これを見やすくするとこうなっています。
8b 05 58 0b 42 00; // EAX = b;
03 05 5c 0b 42 00; // EAX += c;
89 05 90 0a 42 00; // _t0 = EAX;
8b 05 90 0a 42 00; // EAX = _t0;
2b 05 60 0b 42 00; // EAX -= d;
89 05 94 0a 42 00; // _t1 = EAX;
8b 05 94 0a 42 00; // EAX = _t1;
89 05 54 0b 42 00; // a = EAX;
-はい、これはひどいです。_t0や_t1に書いたり読み込んだり、...
-これに対して、理想形はこうなります。
8b 05 58 0b 42 00; // EAX = b;
03 05 5c 0b 42 00; // EAX += c;
2b 05 60 0b 42 00; // EAX -= d;
89 05 54 0b 42 00; // a = EAX;
-っていうか、普通こうなるべきですよね。
----
-もう一つ気になっているのは、このコンパイル結果です。
>if (a+b<c-d) { x=0; }
8b 05 54 0b 42 00; // EAX = a;
03 05 58 0b 42 00; // EAX += b;
89 05 90 0a 42 00; // _t0 = EAX;
8b 05 5c 0b 42 00; // EAX = c;
2b 05 60 0b 42 00; // EAX -= d;
89 05 94 0a 42 00; // _t1 = EAX;
8b 05 90 0a 42 00; // EAX = _t0;
3b 05 94 0a 42 00; // if (EAX < _t1) { EAX = 1: } (S...
0f 9c c0;
0f b6 c0;
89 05 98 0a 42 00; // _t2 = EAX;
8b 05 98 0a 42 00; // EAX = _t2;
85 c0; // if (EAX == 0) goto skip;
0f 84 0c 00 00 00;
8b 05 0c 0a 42 00; // EAX = 0;
89 05 64 0b 42 00; // x = EAX;
skip:
-これがだめだなあと思うのは、_t2への無駄な読み書きと、0f_...
8b 05 54 0b 42 00; // EAX = a;
03 05 58 0b 42 00; // EAX += b;
89 05 90 0a 42 00; // _t0 = EAX;
8b 05 5c 0b 42 00; // EAX = c;
2b 05 60 0b 42 00; // EAX -= d;
89 05 94 0a 42 00; // _t1 = EAX;
8b 05 90 0a 42 00; // EAX = _t0;
3b 05 94 0a 42 00; // if (EAX >= _t1) goto skip;
0f 8d 0c 00 00 00;
8b 05 0c 0a 42 00; // EAX = 0;
89 05 64 0b 42 00; // x = EAX;
skip:
----
-ということで、HL-15はこの2つの問題を解決しようと思います。
-[1]regVar()関数の後、putIcX86_sub()関数の前に以下を追加
unsigned char *icq0, *icq1, *icqSet;
void optimizerX86()
{
int i;
if (icq0 != icq) {
if (icq0[0] == 0x0f && 0x90 <= icq0[1] && icq0[1...
icqSet = icq0;
}
if (icq0[0] == 0x8b && icq1 != 0 && icq1[0] == 0...
icq = icq0; // 8b命令は削除.
i = (IntP) get32(icq1 + 2) - var;
if (TcTmp0 <= i && i <= TcTmp9) {
icq = icq1; // 89命令も削除.
}
}
icq1 = icq0;
icq0 = icq;
}
if (icqSet + 14 == icq && memcmp(&icqSet[2], "\xc0\x...
memcpy(&icqSet[2], &icqSet[10], 4);
icqSet[1] -= 0x10; // SETcc → Jcc.
if (icqSet[9] == 0x84) {
icqSet[1] ^= 1; // 条件反転.
}
icq0 = icq = icqSet + 6;
icq1 = icqSet = 0;
jmps[jp - 1] = icq - 4 - ic;
}
}
-[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 (s[i] == ';') {
+ i++;
+ optimizerX86();
} else if (getHex(s[i]) >= 0 && getHex(s[i + 1]) ...
(中略)
}
-[3]defLabel()関数に一行追加
void defLabel(int i)
{
var[i] = icq - ic;
+ icq1 = icqSet = 0;
}
-compile()関数を少し改造
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 = icq0 = ic;
jp = 0;
+ icq1 = icqSet = 0;
putIcX86("60; 83_ec_7c;", 0, 0, 0, 0); // PUSHAD(); ...
regVarSaveLoad(RvLoad);
dump0 = icq;
(中略)
}
----
-以上すべての改造を終えると、プログラムは942行になります。
-さて、うまく動くでしょうか。
>a=b+c-d
8b 05 30 0b 42 00 03 05 34 0b 42 00 2b 05 38 0b 42 00 89...
(len=24)
-うまくいっています。ちゃんと上記の理想通りになっています。
-if文のほうはどうでしょうか。
>if (a+b<c-d) { x=0; }
8b 05 2c 0b 42 00 03 05 30 0b 42 00 89 05 a0 0a 42 00 8b...
8b 05 a0 0a 42 00 3b 05 a4 0a 42 00 0f 9c c0 83 e0 01 85...
89 05 60 0b 42 00
(len=74)
-これもうまくいっています!
** (2) プログラムの説明
-今回の改造の中心は、optimizerX86()関数です。
-この関数は、putIcX86()でセミコロンが来たタイミングで呼ば...
-まず、3つのグローバル変数があります。
--icq0 : 直前のセミコロンの位置(=今の命令の開始位置)
--icq1 : さらにその前のセミコロンの位置(=1つ前の命令の...
--icqSet : SETcc命令を見つけたら、その先頭を記憶しておく
-icqとicq0とicq1を使えば、連続した2命令をチェックすること...
-またSETcc命令の後に最適化すべきパターンが来ていたら、前...
-最適化対象の機械語フレーズの中にラベルがあると、どこから...
** (3) 成果の比較
-上記みたいなのはすごく特別でレアケースなのか、それともよ...
-サイズが小さくなったからいいとか悪いとかではなく、「サイ...
||HL-13a|HL-14|HL-14a|HL-15|
|mandel.c|RIGHT:1087|RIGHT:1007|RIGHT:942|RIGHT:768|
|maze.c|RIGHT:2192|RIGHT:2192|RIGHT:2192|RIGHT:1770|
|kcube.c|RIGHT:4623|RIGHT:4623|RIGHT:4623|RIGHT:3695|
|invader.c|RIGHT:3260|RIGHT:3260|RIGHT:3260|RIGHT:2750|
** 次回に続く
-次回: [[a21_txt02_5a]]
*こめんと欄
#comment
ページ名: