📄 myvm.c
字号:
} } fclose(bin);}/* mksymtab()1st pass scan for constructing symbol table*/void mksymtab(int *err){ char words[20]; char tpwords[15]; int labelidx; int tokencnt = 0; /* the counts of tokens */ int symcnt = 0; MC_opcodes opcode; refnode *refs, *refsa, *newnode; tokentype tokencat; while (!feof(src)) { tokencat = ASlex(words, &opcode); /* read a word, and then identify its cat */ if (tokencat != CMNT) /* ignore any comment which is led with ";" */ tokencnt++; else continue; switch (tokencat) { case LABEL: { int seekResult = seeklabel(words, 0); if (seekResult == -1) { /* a new label found, save to symbol table */ strcpy(symtabhdr[symcnt].symname, words); symtabhdr[symcnt].symaddr = tokencnt - symtablen(); symtabhdr[symcnt].firstref = NULL; symcnt++; } else if (seekResult == -2) { /* duplicated label found, error! */ (*err)++; } } break; case REFLABEL: /* a reference to a label occured */ strcpy(tpwords, words); strcat(tpwords, ":"); labelidx = seeklabel(tpwords, 1); if (labelidx == -1) {#ifdef DEBUG /* forward referencing ,warning ouputed */ printf ("Pass1 warning: label not defined by now: '%s:' , addr:%2d, ignored!\n", words, tokencnt);#endif ; } else { /* backward referencing , link it to link list */ newnode = (refnode *) malloc(sizeof(refnode)); newnode->refsymaddr = tokencnt - 1; newnode->nextref = NULL; if (symtabhdr[labelidx].firstref == NULL) { symtabhdr[labelidx].firstref = newnode; } else { refs = symtabhdr[labelidx].firstref; refsa = refs; while (refs != NULL) { refsa = refs; refs = refs->nextref; } refsa->nextref = newnode; } } break; case UNRECOGNIZED: /* unknown token, ignore it */#ifdef DEBUG printf("Pass1 Warning: Unknown token: %d %s(%d) %d\n", tokencat, words, tokencnt, feof(src)); /* (*err)++; */#endif break; }#ifdef DEBUG printf("(%2d) %d %-8s(%d)\n", opcode != MAXINSTUCTION ? opcode : -1, tokencat, words, tokencnt);#endif }#ifdef DEBUG /* output symbol talbe just built */ printf("\n<<<< Symbol table constructed >>>>\n"); { int i = 0; for (i = 0; i < symcnt; i++) { printf("%s %d %x -> ", symtabhdr[i].symname, symtabhdr[i].symaddr, symtabhdr[i].firstref); if (symtabhdr[i].firstref != NULL) { refs = symtabhdr[i].firstref; while (refs != NULL) { printf("%d %x -> ", refs->refsymaddr, refs->nextref); refs = refs->nextref; } printf("\n"); } printf("\n"); } } printf("<<<< Symbol table above >>>>\n"); /* symbol talbe constructed */#endif}/* return the instruction i's length,i.e. how many bytes it is comprised */int getmnxlen(int i){ return mnxlen[i];}/* lookUpCmds()query instruction table for retrieving the opcode of cmd, the array index impliesopcode*/MC_bytes lookUpCmds(char *cmd){ int i = 0; while (i < MAXINSTUCTION && strcmp(getmns(i), cmd)) { i++; } return (MC_bytes) i;}/* ASlex:lexical analyzing for source file, it extracts a word which seperated by SPACE, save the word to words,querying instruction table for its opcode if it is a assembly instuction and save its opcode to opcode,also determining which category the word belong to and return the category ID to the caller*/tokentype ASlex(char *words, MC_opcodes * opcode){ char cmds[20]; char ch; MC_bytes cds; tokentype tks = CMNT; /* default token cat set to CMNT, comment */ int i = 0; cmds[0] = 0; ch = (char) toupper(fgetc(src)); while (ch <= ' ' && !feof(src) ) /* skip all chars ranged from 00~0x20, seperators */ ch = toupper(fgetc(src)); if (isalpha(ch)) { /* address label or instruction */ do { cmds[i % 20] = ch; i++; ch = toupper(fgetc(src)); } while (ch > ' ' && (isalpha(ch) || isdigit(ch)) && !feof(src)); if (ch == ':') { /* the trailing ":" means a label definition */ cmds[i % 20] = ch; i++; } /* to determine if the word is an instruction */ cmds[i % 20] = '\0'; strcpy(words, cmds); cds = lookUpCmds(cmds); /* querying up instruction table */ *opcode = (MC_opcodes) cds; if (cds == MAXINSTUCTION && words[strlen(words) - 1] == ':') tks = LABEL; /* the word just read is a label definition */ else if (cds == MAXINSTUCTION && words[strlen(words) - 1] != ':') tks = REFLABEL; /* the word just read is a label reference */ else tks = ASMCODE; /* the word just read is a instruction */ } else if (isdigit(ch)) { /* numeric string: any number sequence */ do { cmds[i] = ch; i++; ch = toupper(fgetc(src)); } while (ch > ' ' && isdigit(ch) && !feof(src)); tks = NUM; /* the word just read is a numeric string */ cmds[i] = 0; strcpy(words, cmds); } else if (ch == ';') { /* string led with ; means a comment */ do { ch = toupper(fgetc(src)); } while (ch != '\n' && !feof(src)); strcpy(words, "CMNT"); *opcode = (MC_opcodes) - 99; tks = CMNT; /* the string read is comment */ } else if (ch != EOF) { /* unknown word or string */ cmds[i] = ch; /* if eof reached and you continue to fgetc(), EOF returned */ i++; cmds[i] = '\0'; strcpy(words, cmds); tks = UNRECOGNIZED; /* unknow token */ } return tks; /* return the token recognized , default tks=CMNT */}/* seeklabel()query symbol table to determine the existence of label lblpurpose=0 to determine if the lbl is defined duplicatelypurpose=1 to determine if the lbl is defined already */int seeklabel(char *lbl, int purpose){ int i = 0; for (i = 0; i < SYMTABLEN && strcmp(symtabhdr[i].symname, lbl); i++); if (i < SYMTABLEN && !purpose) { printf("label '%s' multiple defined ,location:%d\n", lbl, symtabhdr[i].symaddr); return -2; /* duplicate label definition */ } else if (i < SYMTABLEN && purpose == 1) { return i; /* return its index in array */ } else { return -1; /* no such label defined */ }}/* symtablen()to get how many labels have defined in symbol table*/int symtablen(){ int i = 0; for (i = 0; i < SYMTABLEN && strcmp(symtabhdr[i].symname, "???????"); i++); return i;}/* test assember */void testas(char *fileName){ int i = 0; /* save error count assembler produced */ AS(fileName); ASassemble(&i); if (i > 0) { printf("MYVM assembler found %d errors in source file\n", i); return; } else { releaseSymtab(); /* free memory allocated for symbol table */ printf("About to execute binary...\n"); runvm(); /* make MYVM run */ }}/* myvm initialization */void initMC(){ MC();}/* release the symbole table ,a link list, created in mksymtab() */void releaseSymtab(){ int i = 0; refnode *refs; for (i = 0; i < SYMTABLEN; i++) { strcpy(symtabhdr[i].symname, ""); symtabhdr[i].symaddr = 0; if (symtabhdr[i].firstref != NULL) { refs = symtabhdr[i].firstref; while (refs != NULL) { symtabhdr[i].firstref = refs->nextref; free(refs); refs = symtabhdr[i].firstref; } } }}/* ########################################## *//* MYVM machine for running assembly language *//* ########################################## *//* ########################################## *//* MYVM Version 0.11a *//* snallie@tom.com 2003.2 *//* ########################################## *//* the CPU structure of MYVM */struct processor { MC_bytes a; /* accumulator a */ MC_bytes sp; /* stack pointer sp */ MC_bytes x; /* index register x */ MC_bytes ir; /* instruction register ir */ MC_bytes pc; /* program counter pc */ MC_bytes bp; /* base pointer bp */ bool z, p, c; /* flag register */};struct processor cpu; /* cpu instance for MYVM */status ps; /* running state of MYVM *//* ########################################## *//* implementaion for MYVM *//* ########################################## *//* ########################################## *//* MYVM Version 0.11a *//* snallie@tom.com 2003.2 *//* ########################################## */const int ESC = 1;/* add 1 to the args x, and guarantee x is between 0 to 255 after the operation done *//* for the cpu can only process 1 byte each time */inline void increment(MC_bytes * x){ *x = (*x + 257) % 256;}/* subtract 1 from the args x, and guarantee x is between 0 to 255 after the operation done */inline void decrement(MC_bytes * x){ *x = (*x + 255) % 256;}/* return the opcode that is represented by str, *//* if str is an invalid instruction then return MC_bad */MC_bytes opcode(char *str){ int i; MC_bytes l = MC_nop; for (i = 0; str[i]; i++) str[i] = toupper(str[i]); while (l <= MAXINSTUCTION && strcmp(str, mnemonics[l])) l++; if (l <= MAXINSTUCTION) return l; else return MC_bad;}/* output all the memory's content of MYVM in hexadecimal, */void listcode(char *srcname){ FILE *listfile; MC_bytes nextbyte = 0, tnb; char filename[256]; int i; newsuffix(srcname, "map", filename); if (*filename == '\0') return; listfile = fopen(filename, "w");/* if (listfile == NULL) *//* listfile = stdout; */ for (i = 1; i <= 16; i++) { int j; /* ??? fprintf */ fprintf(listfile, "%02X(%03d) ", (i - 1) * 16, (i - 1) * 16); tnb = nextbyte; for (j = 1; j <= 16; j++) { fprintf(listfile, "%02X %s", mem[nextbyte], (j == 8) ? " " : ""); increment(&nextbyte); } fprintf(listfile, " "); nextbyte = tnb; for (j = 1; j <= 16; j++) { fprintf(listfile, "%c", (mem[nextbyte] < 0x20) ? '.' : mem[nextbyte]); increment(&nextbyte); } putc('\n', listfile); } /* if (listfile != stdout) */ fclose(listfile);}/* trace the cpu's running process when trace function is enabled */void trace(FILE * results, MC_bytes pcnow){ fprintf(results, "PC=%02X A=%02X ", pcnow, cpu.a); fprintf(results, "X=%02X SP=%02X [SP]=%02X BP=%02X ", cpu.x, cpu.sp, mem[cpu.sp], cpu.bp); fprintf(results, "Z=%d P=%d C=%d ", cpu.z, cpu.p, cpu.c); fprintf(results, "OPCODE=%02X (%s)\n", cpu.ir, mnemonics[cpu.ir]);}/* cope with the runtime error */void runtime_error(FILE * results, MC_bytes pcnow){ switch (ps) { case badop: fprintf(results, "Illegal opcode"); break; case nodata: fprintf(results, "No more data"); break; case baddata: fprintf(results, "Invalid data"); break; } fprintf(results, " at %d\n", pcnow); trace(results, pcnow); printf ("\nRuntime error happend, dumping memory to runtime.err.map ...\n"); listcode("runtime.err.dump"); /* dump runtime error to runtime.err.map file */}/* set flag register z and p */inline void setflags(MC_bytes MC_register){ cpu.z = (MC_register == 0); cpu.p = (MC_register <= 127);}/* evaluating index addressing: X+B, it indicates a mem address ranged from 0~255 */inline MC_bytes index(void){ return ((mem[cpu.pc] + cpu.x) % 256);}/* read a char from data */void readchar(FILE * data, char *ch, status * ps){ if (feof(data)) { *ps = nodata; *ch = ' '; return; } *ch = getc(data); if (*ch == ESC) *ps = finished; if (*ch < ' ' || feof(data)) *ch = ' ';}/* convert the content of char ch to hexadecimal */int hexdigit(char ch){ char tpch; tpch = ch; if (isalpha(ch) && (tpch | 0x20 >= 'a' && tpch | 0x20 <= 'f')) return (ch + 10 - 'a'); if (isdigit(ch)) return (ch - '0'); else return (0);}/* read a number from data in desired radix , the format of number may be {+|-}?{digit}* */int getnumber(FILE * data, int base, status * ps){ bool negative = false; char ch; int num = 0; do { readchar(data, &ch, ps);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -