* 川合のプログラミング言語自作のためのテキスト第二版#0010 -(by [[K]], 2019.06.30) ** (18) TJ-03x -次はTJ-03aを書き直してみます。やってみたら61行になりました。 #include "kll0.h" enum { EAX = 0, ECX = 1 }; void sub_print(int i) { printf("%d\n", i); } void sub_time() { printf("time=%.3f[sec]\n", clock() / (double) CLOCKS_PER_SEC); } int main(int argc, const char **argv) { KLexer lx(NEW1(kautoreleasePool, KStringId)("; = + - print while ( < ) { } time")); char *txt = (char *) kerrorExitP0(kreadFileA(argv[1], "rt", 2), "usage>%s program-file", argv[0]); KLexer_Elmt *le = (KLexer_Elmt *) lx.add(txt)->p; int pc = 0, qc = 0, wqc = 0, wqc2 = 0, *var = (int *) kautoreleasePool->alloc((*lx.sid->n) * sizeof (int)); for (int i = 0; i < *lx.sid->n; i++) var[i] = lx.getConstInt(i); // intではないときは0を返す. unsigned char *code = (unsigned char *) kmallocRWX(1024 * 1024); qc += kputBin(&code[qc], "83_ec_7c"); // SUB ESP,124. この命令でスタックを調整させる. for (int n = lx.getElmtLen(); pc < n; pc++) { if (le[pc + 1].i == 1) { // 2単語目が"=". if (le[pc + 3].i == 0) { // 単純代入. qc += kputBin(&code[qc], "8b_%i8_%i32 a3_%i32", EAX * 8 + 0x05, &var[le[pc + 2].i], &var[le[pc].i]); } else if (le[pc + 3].i == 2 && le[pc + 5].i == 0) { // 加算. qc += kputBin(&code[qc], "8b_%i8_%i32 8b_%i8_%i32 01_c8 a3_%i32", EAX * 8 + 0x05, &var[le[pc + 2].i], ECX * 8 + 0x05, &var[le[pc + 4].i], &var[le[pc].i]); } else if (le[pc + 3].i == 3 && le[pc + 5].i == 0) { // 減算. qc += kputBin(&code[qc], "8b_%i8_%i32 8b_%i8_%i32 29_c8 a3_%i32", EAX * 8 + 0x05, &var[le[pc + 2].i], ECX * 8 + 0x05, &var[le[pc + 4].i], &var[le[pc].i]); } else goto err; } else if (le[pc].i == 5 && le[pc + 1].i == 6 && le[pc + 3].i == 7 && le[pc + 5].i == 8 && le[pc + 6].i == 9) { // while. wqc = qc; qc += kputBin(&code[qc], "8b_%i8_%i32 8b_%i8_%i32 39_c8 0f_8d_%i32", EAX * 8 + 0x05, &var[le[pc + 2].i], ECX * 8 + 0x05, &var[le[pc + 4].i], &var[le[pc].i], 0); wqc2 = qc; pc += 7 - 1; continue; } else if (le[pc].i == 10) { qc += kputBin(&code[qc], "e9_%r32", &code[wqc]); kputBin(&code[wqc2 - 4], "%r32", &code[qc]); continue; } else if (le[pc].i == 11 && le[pc + 1].i == 0) { // time. qc += kputBin(&code[qc], "e8_%r32", sub_time); } else if (le[pc].i == 4 && le[pc + 2].i == 0) { // print. qc += kputBin(&code[qc], "8b_%i8_%i32 89_04_24 e8_%r32", EAX * 8 + 0x05, &var[le[pc + 1].i], sub_print); } else goto err; while (le[pc].i != 0) pc++; } qc += kputBin(&code[qc], "83_c4_7c c3"); // ADD ESP,124. 最初に調整したスタックを元に戻す. RET. void (*func)(); // funcは関数へのポインタ型の変数. func = (void (*)()) code; func(); exit(0); err: kerrorExit("syntax error : %.30s", le[pc].p0); } ** 次回に続く -次回: [[text0021]] *こめんと欄 #comment