[1]関数compile()を以下のように改造
int aryInitList[100], ailp; // この行追加.
char varOpt[MAX_TC + 1]; // この行追加.
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] = TcDot; // エラー表示用のために末尾にピリオドを登録しておく.
icq = icq0 = ic;
! jp = ailp = 0;
icq1 = icqSet = 0;
putIcX86("60; 83_ec_7c;", 0, 0, 0, 0); // PUSHAD(); SUB(ESP,124);
regVarSaveLoad(RvLoad);
dump0 = icq;
for (i = 0; i < 10; i++) {
tmp_flag[i] = 0;
}
tmpLabelNo = 0;
for (i = 0; i < MAX_TC + 1; i++) {
vc[i] = 0;
! varOpt[i] = 0;
}
bd = lbd = 0;
toExit = tmpLabelAlloc();
for (pc = 0; pc < pc1; ) { // コンパイル開始.
(中略)
} else if (phrCmp( 0, "!!*0:", pc)) { // ラベル定義命令.
defLabel(tc[wpc[0]]); // ラベルに対応するicqを記録しておく.
+ varOpt[tc[wpc[0]]] |= 1;
} else if (phrCmp( 5, "goto !!*0;", pc)) { // goto.
(中略)
} else if (phrCmp(22, "int !!*0[!!**2] = {", pc)) {
e2 = expr(2);
putIcX86("8b_%1m0; 89_44_24_00; e8_%2r; 89_%0m0;", &var[tc[wpc[0]]], &var[e2], (IntP) sub_aryNew, 0);
j = 0;
for (i = ppc1; i < pc1; i++) { // コンマ以外のトークンを数える.
if (tc[i] == TcCrBrCls) break;
if (tc[i] != TcComma) {
j++;
}
}
if (i >= pc1) goto err;
AInt *ip = malloc(j * sizeof (AInt));
j = 0;
for (i = ppc1; tc[i] != TcCrBrCls; i++) {
if (tc[i] == TcCrBrCls) break;
if (tc[i] != TcComma) {
ip[j] = var[tc[i]];
j++;
}
}
+ aryInitList[ailp] = icq - ic; // sub_aryInitの呼び出し位置を記憶しておく.
+ ailp++;
! putIcX86("89_44_24_00; b8_%0i; 89_44_24_04; b8_%1i; 89_44_24_08; e8_%2r;", (IntP) ip, (IntP) j, (IntP) sub_aryInit, 0);
ppc1 = i + 2; // } と ; の分.
} else if (phrCmpPutIcX86(23, "aSetPix0(!!***8, !!**0, !!**1, !!**2);", pc, 0, 3, sub_aSetPix0, &e0)) {
(中略)
}
(中略)
for (i = 0; i < jp; i++) { // ジャンプ命令の最適化.
(中略)
}
+ if (codedump != 2) {
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;
(中略)
}
[2]関数run()の直前に以下の関数群を追加
String regNamX86[8] = { "EAX", "ECX", "EDX", "EBX", "ESP", "EBP", "ESI", "EDI" };
int modRmX86(unsigned char *p, char *s)
{
int c0 = *p;
if ((c0 & 0xc0) == 0xc0) {
strcpy(s, regNamX86[c0 & 7]);
return 1;
}
if ((c0 & 0xc7) == 0x05) {
sprintf(s, "DWORD [.%s]", ts[(IntP) get32(p + 1) - var]);
return 5;
}
if ((c0 & 0xc7) == 0x04 && p[1] == 0x8a) {
sprintf(s, "DWORD [EDX+ECX*4]");
return 2;
}
if ((c0 & 0xc7) == 0x44 && p[1] == 0x24) {
sprintf(s, "DWORD [ESP+%d]", p[2]);
return 3;
}
printf("modRmX86: error: %02x\n", c0);
exit(1);
}
String asmX86_sub1(int q, String p0, String s, String p1, String t)
// (q) 1:modRmの直前の1バイトの下位3bitがレジスタを指定, 2:modRm内の中間3bitがレジスタを指定, 3:modRmを解釈した結果.
// 4:8bit即値, 5:32bit即値, 6:CL, 7:sub関数呼び出し, 8:JMP/Jccの分岐先ラベル.
{
if (q == 1) { return regNamX86[p0[-1] & 7]; }
if (q == 2) { return regNamX86[(p0[0] >> 3) & 7]; }
if (q == 3) { return s; }
if (q == 4) { sprintf(t, "%d", *((signed char *) p1)); return t; }
if (q == 6) { return "CL"; }
if (q == 8) { sprintf(t, ".%s", ts[((IntP) get32(p1)) - var]); return t; }
if (q == 5) {
int i = get32(p1), j;
sprintf(t, "%d", i);
for (j = 0; j < tcs; j++) {
if (var[j] == i && ts[j][0] == 34) {
sprintf(t, ".str%d", i);
varOpt[j] |= 2;
}
}
return t;
}
if (q == 7) {
void *sub = p1 + 4 + get32(p1);
if (sub == sub_print) { return "_sub_print"; }
if (sub == sub_time) { return "_sub_time"; }
if (sub == sub_aRgb8) { return "_sub_aRgb8"; }
if (sub == sub_XorShift) { return "_sub_XorShift"; }
if (sub == sub_aGetPix) { return "_sub_aGetPix"; }
if (sub == sub_f16Sin) { return "_sub_f16Sin"; }
if (sub == sub_f16Cos) { return "_sub_f16Cos"; }
if (sub == sub_aInkey) { return "_sub_aInkey"; }
if (sub == sub_prints) { return "_sub_prints"; }
if (sub == sub_aSetPix0) { return "_sub_aSetPix0"; }
if (sub == sub_aFilRct0) { return "_sub_aFilRct0"; }
if (sub == sub_aDrwStr0) { return "_sub_aDrwStr0"; }
if (sub == sub_gprDec) { return "_sub_gprDec"; }
if (sub == sub_OpnWin) { return "_sub_OpnWin"; }
if (sub == sub_aWait) { return "_sub_aWait"; }
if (sub == sub_bitblt) { return "_sub_bitblt"; }
if (sub == sub_aryNew) { return "_sub_aryNew"; }
if (sub == sub_aryInit) { return "_sub_aryInit"; }
}
return "?";
}
int asmX86_sub0(unsigned char *p, String op)
{
char s[100], t[100];
int len = 0, q0 = op[1] - '0', q1 = op[2] - '0', q2 = op[3] - '0';
p++;
String p0 = p;
if (op[0] == 'm') {
len = modRmX86(p, s);
p += len;
}
printf(" %-8s", op + 4);
if (q0 > 0) { printf( "%s", asmX86_sub1(q0, p0, s, p, t)); len += "000014044"[q0] - '0'; }
if (q1 > 0) { printf(",%s", asmX86_sub1(q1, p0, s, p, t)); len += "000014044"[q1] - '0'; }
if (q2 > 0) { printf(",%s", asmX86_sub1(q2, p0, s, p, t)); len += "000014044"[q2] - '0'; }
printf("\n");
return len + 1;
}
char asmX86_jcc[16][4] = { "O", "NO", "B", "AE", "E", "NE", "BE", "A", "S", "NS", "P", "NP", "L", "GE", "LE", "G" };
char asmX86_table0[][16] = {
"0039m230ADD", "02b9m230SUB", "0319m320XOR", "03b9m230CMP",
"0609_000PUSHAD", "0619_000POPAD", "0699m235IMUL", "06b9m234IMUL",
"0810m350ADD", "0814m350AND", "0815m350SUB", "0816m350XOR", "0817m350CMP",
"0830m340ADD", "0834m340AND", "0835m340SUB", "0836m340XOR", "0837m340CMP",
"0859m320TEST", "0899m320MOV", "08b9m230MOV", "0999_000CDQ",
"0c39_000RET", "0c79m350MOV", "0e89_700CALL",
"0c14m340SHL", "0c15m340SHR", "0c17m340SAR", "0d34m360SHL", "0d35m360SHR", "0d37m360SAR",
"0f73m300NEG", "0f75m300IMUL", "0f77m300IDIV",
"1ac9m324SHRD", "1ad9m326SHRD", "1af9m230IMUL", "x"
};
void asmX86()
{
int i, j, k = 0;
if (dump0 == dump1) return;
printf("BITS 32\n");
printf("SECTION .text\n");
printf("GLOBAL _aMain\n");
printf(" ALIGNB 16\n");
printf("_aMain:\n");
for (i = 0; i < jp; i++) {
icq = jmps[i] + ic;
j = ((IntP) get32(icq)) - var;
varOpt[j] |= 1; // 利用したラベルをマークする.
}
for (i = 0;;) {
int c0 = ic[i], c1;
String op = 0;
char t[16];
for (j = 0; j < tcs; j++) {
if (var[j] == (AInt) i && (varOpt[j] & 1) != 0) {
printf(".%s:\n", ts[j]); // ラベル定義出力.
}
}
if (c0 == 0x0f) {
i++;
c0 = ic[i] + 0x100;
}
if (k < ailp && aryInitList[k] + 4 == i) {
printf(" MOV EAX,.ary%d\n", get32(&ic[i + 1]));
i += 5;
k++;
continue;
}
c1 = c0 & ~0xf;
if (c1 == 0x180) {
sprintf(t, "_800J%s", asmX86_jcc[c0 & 0xf]);
op = t;
goto skip;
}
if (c1 == 0x190) {
printf(" SET%-5sAL\n", asmX86_jcc[c0 & 0xf]);
printf(" MOVZX EAX,AL\n");
i += 5;
continue;
}
c1 = c0 & ~0x7;
if (c1 == 0x040) { op = "_100INC"; goto skip; }
if (c1 == 0x048) { op = "_100DEC"; goto skip; }
if (c1 == 0x0b8) { op = "_150MOV"; goto skip; }
c1 = (ic[i + 1] >> 3) & 7;
for (j = 0; asmX86_table0[j][0] != 'x'; j++) {
op = &asmX86_table0[j][4];
if (c0 != getHex(op[-4]) * 256 + getHex(op[-3]) * 16 + getHex(op[-2])) continue;
if (op[-1] != '9' && c1 != op[-1] - '0') continue;
goto skip;
}
printf("asmX86: error: %02x-%02x\n", c0, c1);
exit(1);
skip:
i += asmX86_sub0(&ic[i], op);
if (c0 == 0x0c3) break;
}
printf("EXTERN _sub_print, _sub_time, _sub_aRgb8, _sub_XorShift\n");
printf("EXTERN _sub_aGetPix, _sub_f16Sin, _sub_f16Cos, _sub_aInkey\n");
printf("EXTERN _sub_prints, _sub_aSetPix0, _sub_aFilRct0, _sub_aDrwStr0\n");
printf("EXTERN _sub_gprDec, _sub_OpnWin, _sub_aWait, _sub_bitblt\n");
printf("EXTERN _sub_aryNew, _sub_aryInit\n");
printf("SECTION .data\n");
printf(" ALIGNB 16\n");
for (j = 0; j < tcs; j++) { // 普通の変数の出力.
if (vc[j] > 0) {
printf(".%-6s DD %d\n", ts[j], var[j]);
}
}
for (k = 0; k < ailp; k++) { // 配列の初期値の出力.
int j1 = get32(&ic[aryInitList[k] + 13]), *ip = (IntP) get32(&ic[aryInitList[k] + 5]);
printf(".ary%d:\n", (int) ip);
for (j = 0; j < j1; j++) {
printf(" DD %d\n", ip[j]);
}
}
for (j = 0; j < tcs; j++) { // 文字列リテラルの出力.
if ((varOpt[j] & 2) != 0) {
printf(".str%d DD %s,0\n", var[j], ts[j]);
}
}
}