voidread_image_file(FILE* file) { /* the origin tells us where in memory to place the image */ uint16_t origin; fread(&origin, sizeof(origin), 1, file); origin = swap16(origin);
/* we know the maximum file size so we only need one fread */ uint16_t max_read = UINT16_MAX - origin; uint16_t* p = memory + origin; size_t read = fread(p, sizeof(uint16_t), max_read, file);
/* swap to little endian */ while (read-- > 0) { *p = swap16(*p); ++p; } }
/* since exactly one condition flag should be set at any given time, set the Z flag */ reg[R_COND] = FL_ZRO;
/* set the PC to starting position */ /* 0x3000 is the default */ enum { PC_START = 0x3000 }; reg[R_PC] = PC_START;
int running = 1; while (running) { /* FETCH */ uint16_t instr = mem_read(reg[R_PC]++); uint16_t op = instr >> 12;
switch (op) { case OP_ADD: {代码6-1} break; case OP_AND: {代码6-2} break; case OP_NOT: {代码6-3} break; case OP_BR: {代码6-4} break; case OP_JMP: {代码6-5} break; case OP_JSR: {代码6-6} break; case OP_LD: {代码6-7} break; case OP_LDI: {代码6-8} break; case OP_LDR: {代码6-9} break; case OP_LEA: {代码6-10} break; case OP_ST: {代码6-11} break; case OP_STI: {代码6-12} break; case OP_STR: {代码6-13} break; case OP_TRAP: {代码6-15} break; case OP_RES: case OP_RTI: default: abort(); break; } } {代码7-4} }
enum { TRAP_GETC = 0x20, /* get character from keyboard, not echoed onto the terminal */ TRAP_OUT = 0x21, /* output a character */ TRAP_PUTS = 0x22, /* output a word string */ TRAP_IN = 0x23, /* get character from keyboard, echoed onto the terminal */ TRAP_PUTSP = 0x24, /* output a byte string */ TRAP_HALT = 0x25/* halt the program */ };
switch (instr & 0xFF) { case TRAP_GETC: {代码6-16} break; case TRAP_OUT: {代码6-17} break; case TRAP_PUTS: {代码6-18} break; case TRAP_IN: {代码6-19} break; case TRAP_PUTSP: {代码6-20} break; case TRAP_HALT: {代码6-21} break; }
trap指令清单:
代码6-16:输入字符
1 2 3 4 5
{ /* read a single ASCII char */ reg[R_R0] = (uint16_t)getchar(); update_flags(R_R0); }
{ /* one char per word */ uint16_t* c = memory + reg[R_R0]; while (*c) { putc((char)*c, stdout); ++c; } fflush(stdout); }
代码6-19:准备输入字符
1 2 3 4 5 6 7 8
{ printf("Enter a character: "); char c = getchar(); putc(c, stdout); fflush(stdout); reg[R_R0] = (uint16_t)c; update_flags(R_R0); }
代码6-20:输出字符串
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
{ /* one char per byte (two bytes per word) here we need to swap back to big endian format */ uint16_t* c = memory + reg[R_R0]; while (*c) { char char1 = (*c) & 0xFF; putc(char1, stdout); char char2 = (*c) >> 8; if (char2) putc(char2, stdout); ++c; } fflush(stdout); }
代码6-21:终止程序
1 2 3 4 5
{ puts("HALT"); fflush(stdout); running = 0; }
7. 头部添加以及windows加入API
加入的头部:
代码7-1:
1 2 3 4 5 6 7 8 9 10 11 12 13
#include<stdio.h> #include<stdlib.h> #include<stdint.h> #include<stdint.h>// uint16_t #include<stdio.h>// FILE #include<signal.h>// SIGINT /* windows only */ #include<Windows.h> #include<conio.h>// _kbhit
voiddisable_input_buffering() { hStdin = GetStdHandle(STD_INPUT_HANDLE); GetConsoleMode(hStdin, &fdwOldMode); /* save old mode */ fdwMode = fdwOldMode ^ ENABLE_ECHO_INPUT /* no input echo */ ^ ENABLE_LINE_INPUT; /* return when one or more characters are available */ SetConsoleMode(hStdin, fdwMode); /* set new mode */ FlushConsoleInputBuffer(hStdin); /* clear buffer */ }