diff --git a/consts.c b/consts.c index efb7fc7..4a9d776 100644 --- a/consts.c +++ b/consts.c @@ -1,6 +1,6 @@ #ifndef CONSTS #define CONSTS -#define VERSION 2 +#define VERSION 3 #endif /* ifndef CONSTS #define CONSTS diff --git a/nja-3 b/nja-3 new file mode 100755 index 0000000..a703832 Binary files /dev/null and b/nja-3 differ diff --git a/njvm-3 b/njvm-3 new file mode 100755 index 0000000..b95021a Binary files /dev/null and b/njvm-3 differ diff --git a/njvm.c b/njvm.c index 6e2e41c..4daa57c 100644 --- a/njvm.c +++ b/njvm.c @@ -12,6 +12,7 @@ struct program *program; // SDA unsigned fp; +int debug = 0; void version(void) { printf("Ninja Virtual Machine version %i (compiled %s, %s)\n", 0, __DATE__, __TIME__); @@ -41,57 +42,78 @@ void execute(struct program *program, struct sda *sda) { for (int i = 0; i < program->size; ++i) { unsigned int instruction = program->program[i]; + if (i >= program->size) { + printf("Error: Jump out of program memory\n"); + goto end; + } + switch (instruction >> 24) { case HALT: goto end; case PUSHC: + if (debug == 1) printf("PUSHC %d\n", SIGN_EXTEND(IMMEDIATE(instruction))); push(&stack, SIGN_EXTEND(IMMEDIATE(instruction))); break; case ADD: + if (debug == 1) printf("ADD\n"); push(&stack, pop(&stack) + pop(&stack)); break; case SUB: tmp = pop(&stack); + if (debug == 1) printf("SUB\n"); + if (debug == 1) printf("tmp: %d\n", tmp); push(&stack, pop(&stack) - tmp); break; case MUL: + if (debug == 1) printf("MUL\n"); push(&stack, pop(&stack) * pop(&stack)); break; case DIV: tmp = pop(&stack); + if (debug == 1) printf("DIV\n"); + if (debug == 1) printf("tmp: %d\n", tmp); push(&stack, pop(&stack) / tmp); break; case MOD: tmp = pop(&stack); + if (debug == 1) printf("MOD\n"); + if (debug == 1) printf("tmp: %d\n", tmp); push(&stack, pop(&stack) % tmp); break; case RDINT: scanf("%i", &intInput); + if (debug == 1) printf("RDINT %d\n", intInput); push(&stack, intInput); break; case WRINT: + if (debug == 1) printf("WRINT\n"); printf("%i", pop(&stack)); break; case RDCHR: scanf("%c", &charInput); + if (debug == 1) printf("RDCHR %c\n", charInput); push(&stack, charInput); break; case WRCHR: + if (debug == 1) printf("WRCHR\n"); printf("%c", pop(&stack)); break; case PUSHG: + if (debug == 1) printf("PUSHG %d\n", SIGN_EXTEND(IMMEDIATE(instruction))); currentFrame = stack.frames[stack.currentFrame]; currentFrame->bp = currentFrame->sp; *currentFrame->sp++ = getSDA(SIGN_EXTEND(IMMEDIATE(instruction)), sda); break; case POPG: + if (debug == 1) printf("POPG %d\n", SIGN_EXTEND(IMMEDIATE(instruction))); currentFrame = stack.frames[stack.currentFrame]; currentFrame->bp = currentFrame->sp; setSDA(SIGN_EXTEND(IMMEDIATE(instruction)), pop(&stack), sda); break; case ASF: + if (debug == 1) printf("ASF %d\n", SIGN_EXTEND(IMMEDIATE(instruction))); currentFrame = stack.frames[stack.currentFrame]; push(&stack, *currentFrame->sp); *currentFrame->sp = stack.currentFrame; @@ -100,47 +122,106 @@ void execute(struct program *program, struct sda *sda) { stack.currentFrame += SIGN_EXTEND(IMMEDIATE(instruction)); break; case RSF: + if (debug == 1) printf("RSF\n"); stack.currentFrame = pop(&stack); currentFrame = stack.frames[stack.currentFrame]; currentFrame->bp = NULL; break; case PUSHL: + if (debug == 1) printf("PUSHL %d\n", SIGN_EXTEND(IMMEDIATE(instruction))); currentFrame = stack.frames[stack.currentFrame]; push(&stack, currentFrame->fp[SIGN_EXTEND(IMMEDIATE(instruction))]); break; case POPL: + if (debug == 1) printf("POPL %d\n", SIGN_EXTEND(IMMEDIATE(instruction))); currentFrame = stack.frames[stack.currentFrame]; currentFrame->fp[SIGN_EXTEND(IMMEDIATE(instruction))] = pop(&stack); break; case EQ: - push(&stack,pop(&stack)==pop(&stack)); + if (debug == 1) printf("EQ\n"); + if (pop(&stack) == pop(&stack)) { + push(&stack, 1); + } else { + push(&stack, 0); + } break; case NE: - push(&stack,pop(&stack)!=pop(&stack)); + if (debug == 1) printf("NE\n"); + if (pop(&stack) != pop(&stack)) { + push(&stack, 1); + } else { + push(&stack, 0); + } break; case LT: - push(&stack, pop(&stack)pop(&stack)); + if (debug == 1) printf("GT\n"); + if (debug == 1) printf("peek(1): %d\n", peek(&stack, 1)); + if (debug == 1) printf("peek(2): %d\n", peek(&stack, 2)); + if (debug == 1) printf("peek(1) > peek(2): %d\n", peek(&stack, 2) > peek(&stack, 1)); + tmp = pop(&stack); + if (pop(&stack) > tmp) { + push(&stack, 1); + } else { + push(&stack, 0); + } break; case GE: - push(&stack,pop(&stack)>=pop(&stack)); + if (debug == 1) printf("GE\n"); + tmp = pop(&stack); + if (pop(&stack) >= tmp) { + push(&stack, 1); + } else { + push(&stack, 0); + } break; case JMP: - i = SIGN_EXTEND(IMMEDIATE(instruction)); + if (debug == 1) printf("JMP %d\n", SIGN_EXTEND(IMMEDIATE(instruction))); + int j = SIGN_EXTEND(IMMEDIATE(program->program[i])); + if (debug == 1) printf("JMP %d\n", j); + if (j-- >= program->size) { + printf("Error: Jump out of program memory\n"); + goto end; + } + i = j; break; - case BRF: - if (pop(&stack)==0){ - i = SIGN_EXTEND(IMMEDIATE(instruction)); + case BRF: // branch on false + if (debug == 1) printf("BRF %d\nStack: %d\n", SIGN_EXTEND(IMMEDIATE(instruction)), pop(&stack)); + if (pop(&stack) == 0) { + int j = SIGN_EXTEND(IMMEDIATE(program->program[i])); + if (j-- >= program->size) { + printf("Error: BRF out of program memory\n"); + goto end; + } + i = j; } break; case BRT: - if (pop(&stack)==1){ - i = SIGN_EXTEND(IMMEDIATE(instruction)); + if (debug == 1) printf("BRT %d\n", SIGN_EXTEND(IMMEDIATE(instruction))); + if (pop(&stack) == 1) { + int j = SIGN_EXTEND(IMMEDIATE(program->program[i])); + if (j-- >= program->size) { + printf("Error: BRT out of program memory\n"); + goto end; + } + i = j; } break; } @@ -153,12 +234,12 @@ void execute(struct program *program, struct sda *sda) { // run prog2.bin void tests(void) { printf("Test started\n"); - struct sda *sda = malloc(sizeof(struct sda)); + /*struct sda *sda = malloc(sizeof(struct sda)); unsigned int s[1000]; sda->size = 1000; sda->sda = s; fromFile("prog2.bin", program); - execute(program, (struct sda *) &sda); + execute(program, (struct sda *) &sda);*/ printf("Test finished\n"); } @@ -177,7 +258,6 @@ int main(int argc, char *argv[]) { program->program = p; // Initialize runtime variables - int debug = 0; int run = 0; int sizeSDA; @@ -214,9 +294,8 @@ int main(int argc, char *argv[]) { unsigned int s[sizeSDA]; sda->size = sizeSDA; sda->sda = s; - printProgram(program); + if (debug == 1) printProgram(program); execute(program, (struct sda *) &sda); - if (debug == 1) printSDA(sda); printf("Ninja Virtual Machine stopped\n"); } else { printf("Error: no code file specified\n"); diff --git a/programs/prog1.bin b/programs/prog1.bin index 9aa0fba..1a5552c 100644 Binary files a/programs/prog1.bin and b/programs/prog1.bin differ diff --git a/programs/prog3.asm b/programs/prog3.asm new file mode 100644 index 0000000..a17f3cd --- /dev/null +++ b/programs/prog3.asm @@ -0,0 +1,61 @@ +// +// prog1.asm -- an assembler example with global variables +// + +// +// compute the gcd of two positive numbers +// +// global Integer x; +// global Integer y; +// x = readInteger(); +// y = readInteger(); +// while (x != y) { +// if (x > y) { +// x = x - y; +// } else { +// y = y - x; +// } +// } +// writeInteger(x); +// writeCharacter('\n'); + + // x = readInteger(); + rdint + popg 0 + // y = readInteger(); + rdint + popg 1 + // while ... +L1: + // x != y + pushg 0 // 4 + pushg 1 + ne + brf L2 + // if ... + pushg 0 + pushg 1 + gt + brf L3 + // x = x - y + pushg 0 + pushg 1 + sub + popg 0 + jmp L4 +L3: + // y = y - x + pushg 1 // 17 + pushg 0 + sub + popg 1 +L4: + jmp L1 // 21 +L2: + // writeInteger(x); + pushg 0 // 22 + wrint + // writeCharacter('\n'); + pushc '\n' + wrchr + halt diff --git a/programs/prog3.bin b/programs/prog3.bin new file mode 100644 index 0000000..da8f524 Binary files /dev/null and b/programs/prog3.bin differ diff --git a/programs/prog4.asm b/programs/prog4.asm new file mode 100644 index 0000000..2361a26 --- /dev/null +++ b/programs/prog4.asm @@ -0,0 +1,63 @@ +// +// prog2.asm -- an assembler example with local variables +// + +// +// compute the gcd of two positive numbers +// +// local Integer x; +// local Integer y; +// x = readInteger(); +// y = readInteger(); +// while (x != y) { +// if (x > y) { +// x = x - y; +// } else { +// y = y - x; +// } +// } +// writeInteger(x); +// writeCharacter('\n'); + + asf 2 + // x = readInteger(); + rdint + popl 0 + // y = readInteger(); + rdint + popl 1 + // while ... +L1: + // x != y + pushl 0 + pushl 1 + ne + brf L2 + // if ... + pushl 0 + pushl 1 + gt + brf L3 + // x = x - y + pushl 0 + pushl 1 + sub + popl 0 + jmp L4 +L3: + // y = y - x + pushl 1 + pushl 0 + sub + popl 1 +L4: + jmp L1 +L2: + // writeInteger(x); + pushl 0 + wrint + // writeCharacter('\n'); + pushc '\n' + wrchr + rsf + halt diff --git a/programs/prog4.bin b/programs/prog4.bin new file mode 100644 index 0000000..36d2c44 Binary files /dev/null and b/programs/prog4.bin differ diff --git a/stack.c b/stack.c index f84d3ab..4eb2c26 100755 --- a/stack.c +++ b/stack.c @@ -38,4 +38,9 @@ int pop(struct stack *stack) { return *--currentFrame->sp; } +int peek(struct stack *stack, int steps) { // peek is pop without removing the value + struct stackFrame *currentFrame = stack->frames[stack->currentFrame]; + return *(currentFrame->sp - steps); +} + #endif