⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 myvm.c

📁 一个小型的操作系统,采用gcc进行开发,几千行的代码,方便初学者学习
💻 C
📖 第 1 页 / 共 3 页
字号:
	    }    }    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 + -