#define SET 0
#define ADD 1
#define SUB 2
#define MUL 3
#define POP 4
#define PUSH 5
#define JMP 6
#define LABEL 7
#define JMPN 7
inline unsigned char masm(int cmd, int arg) {
return cmd != JMP || arg >= 0 ? (cmd << 5) | arg : (cmd << 5) | 16 | (-arg);
}
int make_init(unsigned char *code, int p) {
code[p++] = masm(PUSH, 0);
code[p++] = masm(POP, 2);
code[p++] = masm(SET, 1);
code[p++] = masm(ADD, 2);
code[p++] = masm(PUSH, 0);
code[p++] = masm(POP, 2); // R2 = arg + 1;
code[p++] = masm(SET, 1);
code[p++] = masm(PUSH, 0);
code[p++] = masm(POP, 1); // R1 = 1
code[p++] = masm(SET, 0);
return p;
}
int make_loopbegin(unsigned char *code, int p) {
code[p++] = masm(LABEL, 1);
return p;
}
int make_loop(unsigned char *code, int p) {
code[p++] = masm(ADD, 1); // 1st, r0 = r0 + r1;
code[p++] = masm(PUSH, 0);
code[p++] = masm(SET, 1);
code[p++] = masm(ADD, 1); // ++r1;
code[p++] = masm(PUSH, 0);
code[p++] = masm(POP, 1);
code[p++] = masm(SUB, 2);
code[p++] = masm(JMP, 2); // if r0 == 0 goto end
code[p++] = masm(SET, 1); // 2nd
code[p++] = masm(ADD, 1); // ++r1;
code[p++] = masm(PUSH, 0);
code[p++] = masm(POP, 1);
code[p++] = masm(SUB, 2);
code[p++] = masm(JMP, 2); // if r0 == 0 goto end
code[p++] = masm(POP, 0);
code[p++] = masm(ADD, 1); // 3rd, r0 = r0 + r1;
code[p++] = masm(ADD, 1);
code[p++] = masm(PUSH, 0);
code[p++] = masm(SET, 1);
code[p++] = masm(ADD, 1); // ++r1;
code[p++] = masm(PUSH, 0);
code[p++] = masm(POP, 1);
code[p++] = masm(SUB, 2);
code[p++] = masm(JMP, 2); // if r0 == 0 goto end
code[p++] = masm(SET, 1); // 4th
code[p++] = masm(ADD, 1); // ++r1;
code[p++] = masm(PUSH, 0);
code[p++] = masm(POP, 1);
code[p++] = masm(SUB, 2);
code[p++] = masm(JMP, 2); // if r0 == 0 goto end
code[p++] = masm(POP, 0);
code[p++] = masm(ADD, 1); // 5th, r0 = r0 + r1;
code[p++] = masm(PUSH, 0);
code[p++] = masm(SET, 1);
code[p++] = masm(ADD, 1); // ++r1;
code[p++] = masm(PUSH, 0);
code[p++] = masm(POP, 1);
code[p++] = masm(SUB, 2);
code[p++] = masm(JMP, 2); // if r0 == 0 goto end
code[p++] = masm(POP, 0);
code[p++] = masm(SUB, 1); // 6th, r0 = r0 - r1;
code[p++] = masm(PUSH, 0);
code[p++] = masm(SET, 1);
code[p++] = masm(ADD, 1); // ++r1;
code[p++] = masm(PUSH, 0);
code[p++] = masm(POP, 1);
code[p++] = masm(SUB, 2);
code[p++] = masm(JMP, 2); // if r0 == 0 goto end
code[p++] = masm(POP, 0);
return p;
}
int make_loopend(unsigned char *code, int p) {
code[p++] = masm(JMP, -1);
code[p++] = masm(LABEL, 2);
return p;
}
int make_end(unsigned char *code, int p) {
code[p++] = masm(POP, 0); // pop r0
return p;
}
int make_code(unsigned char *code) {
int p = 0;
p = make_init(code, p);
p = make_loopbegin(code, p);
p = make_loop(code, p);
p = make_loopend(code, p);
p = make_end(code, p);
return p;
}
int run_code(unsigned char *code, int size, int arg) {
int cmd[10000];
int par[10000];
int SP, S[1000];
int label[16];
int R[17];
for (int i = 0; i < 16; ++i)
label[i] = -2;
register int p = 0;
for (register int i = 0; i < size; ++i) {
cmd[p] = code[i] >> 5;
if (cmd[p] == LABEL){
label[code[i] & 0x0f] = p - 1;
continue;
}
if (cmd[p] == JMP) {
if (code[i] & 0x10)
cmd[p] = JMPN;
par[p] = code[i] & 0x0f;
} else {
par[p] = code[i] & 0x1f;
}
++p;
}
size = p;
for (int i = 0; i < 16; ++i)
R[i] = 0;
R[0] = arg;
SP = 0;
p = 0;
while(p < size) {
int &c = cmd[p], &a = par[p];
if (c < 4) {
if (c < 2) {
if (c == 0) {
R[0] = a;
} else {
R[0] += R[a];
}
} else {
if (c == 2) {
R[0] -= R[a];
} else {
R[0] *= R[a];
}
}
} else {
if (c < 6) {
if (c == 4) {
if (SP > 0)
R[a] = S[--SP];
} else {
if (SP < 1000)
S[SP++] = R[a];
}
} else {
if (c == 6) {
if (!R[0] && label[a] != -2)
p = label[a];
} else {
if (R[0] && label[a] != -2)
p = label[a];
}
}
}
++p;
}
return R[0];
}
댓글