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

📄 myvm.c

📁 一个小型的操作系统,采用gcc进行开发,几千行的代码,方便初学者学习
💻 C
📖 第 1 页 / 共 3 页
字号:
/**  Snixos Project version 1.0, 2003.6*  (C) Copyright 2003,2004,2005 Jockeyson,KeqiangGao <Snallie@tom.com>*  All Rights Reserved.*  Distributed under the terms of the GNU General Public License.**  This program is a free and open source software and you can redistribute *  it and/or modify it under the terms of the GNU General Public License as*  published by the Free Software Foundation. As no any liability is assumed *  for any incidental or consequential damages in connection with the *  information or program fragments contained herein,so any exception arised*  is at your own risk. It is ABSOLUTELY WITHOUT ANY WARRANTY.*  Bug report please send to Snallie@tom.com .*//*  myvm.c : utility in Snixos served as a virtual machine for running myvm assembly language,	   ported from MYVM Version 0.11a written in C++ in 2003, for more about MYVM mail the author.   Author : Snallie@tom.com  Time   : 2004.6*//* to make in Linux individually: gcc -D_NATIVE myvm.c -o myvm */#ifndef _NATIVE#	include "fatfs.h"#	include "mem.h"#endif#include "stdio.h"#if __MSDOS__ || MSDOS || WIN32 || __WIN32__#  define  pathsep '\\'#else#  define  pathsep '/'#endif#define  false 0#define  true 1#define  boolean  int#define  bool     int#define  maxint   2147483647	/* INT_MAX defined in limit.h */#define  MAXINSTUCTION  67	/* how many instructions MYVM understands */#define  MEMSIZE  256		/* the size of memory for MYVM to store assembled machine code */#define  SYMTABLEN 50		/* capacity of symbol table */#define  MAXSYMLEN 32		/* the maximum characters a symbol comprised */typedef unsigned char MC_bytes;typedef struct refnodes {    MC_bytes refsymaddr;	/* the address a address label referenced */    struct refnodes *nextref;	/* the next referenced node for the same address */} refnode;typedef struct symtab {    char symname[MAXSYMLEN];	/* an address represented in string format */    MC_bytes symaddr;		/* the memory address referenced by symname */    struct refnodes *firstref;	/* the first reference to symname */} symboltab;/* token type  return by  lex() *//* ASMCODE:assembly  instruction;  LABEL:a address defined; *//* REFLABEL:a reference to LABEL; NUM:a numeric string; ID:identifier; *//* CMNT: commentation in source;  UNRECOGNIZED: unknown token */typedef enum tktype {    ASMCODE, LABEL, REFLABEL, NUMBER, ID, NUM, CMNT, UNRECOGNIZED} tokentype;/* MYVM machine instruction, the order here may not be modified ! */typedef enum MC_opcode {    /* 0-7 */ MC_nop, MC_clra, MC_clrc, MC_clrx, MC_cmc, MC_inc, MC_dec,    MC_incx,    /* 8-f */ MC_decx, MC_tax, MC_ini, MC_inh, MC_inb, MC_ina, MC_oti,    MC_otc,    /* 10-17 */ MC_oth, MC_otb, MC_ota, MC_push, MC_pop, MC_shl, MC_shr,    MC_ret,    /* 18-1f */ MC_halt, MC_lda, MC_ldx, MC_ldi, MC_lsp, MC_lspi, MC_sta,    MC_stx,    /* 20-27 */ MC_add, MC_adx, MC_adi, MC_adc, MC_acx, MC_aci, MC_sub,    MC_sbx,    /* 28-2f */ MC_sbi, MC_sbc, MC_scx, MC_sci, MC_cmp, MC_cpx, MC_cpi,    MC_ana,    /* 30-37 */ MC_anx, MC_ani, MC_ora, MC_orx, MC_ori, MC_jmp, MC_bze,    MC_bnz,    /* 38-3f */ MC_bpz, MC_bng, MC_bcc, MC_bcs, MC_tsp, MC_jsr, MC_lbpi,    MC_fbpi,    /* 40~ */ MC_tbp, MC_tsb, MC_tabp, MC_bad = 255} MC_opcodes;/* the running state definition for MYVM */typedef enum { running, finished, nodata, baddata, badop } status;FILE *src;			/* asm source file FILE * pointer */char srcfile[20];		/* to save source file name ,file name may be less than 20 */symboltab symtabhdr[SYMTABLEN];	/* symbol array */MC_bytes mem[256];		/* memory space for MYVM */char *mnemonics[256];		/* machine code vs mnemonics */int mnxlen[256];		/* table to save each machine code's length */int binlen;			/* binary file length */void mksymtab(int *err);MC_bytes lookUpCmds(char *cmd);tokentype ASlex(char *words, MC_opcodes * opcode);int seeklabel(char *lbl, int purpose);int symtablen();void AS(char *sourcename);char *getmns(int i);void MC();MC_bytes MCopcode(char *str);void newsuffix(char *oldstr, char *ext, char *newstr);void ASassemble(bool * errors);int seeklabel(char *lbl, int purpose);int symtablen();void initMC();void releaseSymtab();void runvm();static void logo();/* abs(number), abs(0)=0,abs(-2)=2, abs(2)=2 */int abs(int i){    return i >= 0 ? i : -i;}/* atoi() *//* convert ascii number string to digit value *//* e.g "-983"->983, "983"->983, "+983"->983 ,any string not leading with number returned 0 */int atoi(char *nbrStr){    int i = 0;    int tp = 0;    if (*(nbrStr + i)	&& (isdigit(*(nbrStr + i)) || *(nbrStr + i) == '+'	    || *(nbrStr + i) == '-')) {	switch (*(nbrStr + i)) {	case '+':	    tp = atoi(nbrStr + 1);	    break;	case '-':	    tp = -(atoi(nbrStr + 1));	    break;	default:	    while (*(nbrStr + i) && isdigit(*(nbrStr + i))) {		tp = tp * 10 + *(nbrStr + i) - 0x30;		i++;	    }	}    }    return tp;}/* ########################################## *//* MYVM Version 0.11a *//* snallie@tom.com  2003.2 *//* 2 pass assembler *//* ########################################## */void AS(char *sourcename){    int i;    strcpy(srcfile, sourcename);    src = fopen(sourcename, "r");    if (src == NULL) {	printf("Could not open input file\n");	return;    }    /* each element in symbol table initialized as '????????' */    for (i = 0; i < SYMTABLEN; i++)	strcpy(symtabhdr[i].symname, "???????");}/* return instruction i's mnemonics */char *getmns(int i){    return mnemonics[i];}/* MYVM initialization: clear memory , instruction table fill up,etc. */void MC(){    int i;    /* memory of MYVM totally fill with MC_bad(0xff) */    for (i = 0; i <= 255; i++)	mem[i] = MC_bad;    /* instrction table filling up */    for (i = 0; i <= 255; i++)	mnemonics[i] = "???";    /* opcode string fill in mnemonics[] ,the index implies opcode 0xxx */    mnemonics[MC_nop] = "NOP";	/* 0x0 */    mnemonics[MC_clra] = "CLRA";	/* 0x1 */    mnemonics[MC_clrc] = "CLRC";	/* 0x2 */    mnemonics[MC_clrx] = "CLRX";	/* 0x3 */    mnemonics[MC_cmc] = "CMC";	/* 0x4 */    mnemonics[MC_inc] = "INC";	/* 0x5 */    mnemonics[MC_dec] = "DEC";	/* 0x6 */    mnemonics[MC_incx] = "INCX";	/* 0x7 */    mnemonics[MC_decx] = "DECX";	/* 0x8 */    mnemonics[MC_tax] = "TAX";	/* 0x9 */    mnemonics[MC_ini] = "INI";	/* 0xa */    mnemonics[MC_inh] = "INH";	/* 0xb */    mnemonics[MC_inb] = "INB";	/* 0xc */    mnemonics[MC_ina] = "INA";	/* 0xd */    mnemonics[MC_oti] = "OTI";	/* 0xe */    mnemonics[MC_otc] = "OTC";	/* 0xf */    mnemonics[MC_oth] = "OTH";	/* 0x10 */    mnemonics[MC_otb] = "OTB";	/* 0x11 */    mnemonics[MC_ota] = "OTA";	/* 0x12 */    mnemonics[MC_push] = "PUSH";	/* 0x13 */    mnemonics[MC_pop] = "POP";	/* 0x14 */    mnemonics[MC_shl] = "SHL";	/* 0x15 */    mnemonics[MC_shr] = "SHR";	/* 0x16 */    mnemonics[MC_ret] = "RET";	/* 0x17 */    mnemonics[MC_halt] = "HALT";	/* 0x18 */    mnemonics[MC_lda] = "LDA";	/* 0x19 */    mnemonics[MC_ldx] = "LDX";	/* 0x1a */    mnemonics[MC_ldi] = "LDI";	/* 0x1b */    mnemonics[MC_lsp] = "LSP";	/* 0x1c */    mnemonics[MC_lspi] = "LSPI";	/* 0x1d */    mnemonics[MC_sta] = "STA";	/* 0x1e */    mnemonics[MC_stx] = "STX";	/* 0x1f */    mnemonics[MC_add] = "ADD";	/* 0x20 */    mnemonics[MC_adx] = "ADX";	/* 0x21 */    mnemonics[MC_adi] = "ADI";	/* 0x22 */    mnemonics[MC_adc] = "ADC";	/* 0x23 */    mnemonics[MC_acx] = "ACX";	/* 0x24 */    mnemonics[MC_aci] = "ACI";	/* 0x25 */    mnemonics[MC_sub] = "SUB";	/* 0x26 */    mnemonics[MC_sbx] = "SBX";	/* 0x27 */    mnemonics[MC_sbi] = "SBI";	/* 0x28 */    mnemonics[MC_sbc] = "SBC";	/* 0x29 */    mnemonics[MC_scx] = "SCX";	/* 0x2a */    mnemonics[MC_sci] = "SCI";	/* 0x2b */    mnemonics[MC_cmp] = "CMP";	/* 0x2c */    mnemonics[MC_cpx] = "CPX";	/* 0x2d */    mnemonics[MC_cpi] = "CPI";	/* 0x2e */    mnemonics[MC_ana] = "ANA";	/* 0x2f */    mnemonics[MC_anx] = "ANX";	/* 0x30 */    mnemonics[MC_ani] = "ANI";	/* 0x31 */    mnemonics[MC_ora] = "ORA";	/* 0x32 */    mnemonics[MC_orx] = "ORX";	/* 0x33 */    mnemonics[MC_ori] = "ORI";	/* 0x34 */    mnemonics[MC_jmp] = "JMP";	/* 0x35 */    mnemonics[MC_bze] = "BZE";	/* 0x36 */    mnemonics[MC_bnz] = "BNZ";	/* 0x37 */    mnemonics[MC_bpz] = "BPZ";	/* 0x38 */    mnemonics[MC_bng] = "BNG";	/* 0x39 */    mnemonics[MC_bcc] = "BCC";	/* 0x3a */    mnemonics[MC_bcs] = "BCS";	/* 0x3b */    mnemonics[MC_tsp] = "TSP";	/* 0x3c */    mnemonics[MC_jsr] = "JSR";	/* 0x3d */    mnemonics[MC_lbpi] = "LBPI";	/* 0x3e */    mnemonics[MC_fbpi] = "FBPI";	/* 0x3f */    mnemonics[MC_tbp] = "TBP";	/* 0x40 */    mnemonics[MC_tsb] = "TSB";	/* 0x41 */    mnemonics[MC_tabp] = "TABP";	/* 0x42 */    /* intruction length table initialization */    for (i = 0; i <= 255; i++)	mnxlen[i] = 1;    mnxlen[MC_lda] = 2;    mnxlen[MC_ldx] = 2;    mnxlen[MC_ldi] = 2;    mnxlen[MC_lsp] = 2;    mnxlen[MC_lspi] = 2;    mnxlen[MC_sta] = 2;    mnxlen[MC_stx] = 2;    mnxlen[MC_lbpi] = 2;    mnxlen[MC_fbpi] = 2;    mnxlen[MC_add] = 2;    mnxlen[MC_adi] = 2;    mnxlen[MC_adc] = 2;    mnxlen[MC_adx] = 2;    mnxlen[MC_acx] = 2;    mnxlen[MC_aci] = 2;    mnxlen[MC_sub] = 2;    mnxlen[MC_sbx] = 2;    mnxlen[MC_sbi] = 2;    mnxlen[MC_sbc] = 2;    mnxlen[MC_scx] = 2;    mnxlen[MC_sci] = 2;    mnxlen[MC_cmp] = 2;    mnxlen[MC_cpx] = 2;    mnxlen[MC_cpi] = 2;    mnxlen[MC_ana] = 2;    mnxlen[MC_anx] = 2;    mnxlen[MC_ani] = 2;    mnxlen[MC_ora] = 2;    mnxlen[MC_orx] = 2;    mnxlen[MC_ori] = 2;    mnxlen[MC_jmp] = 2;    mnxlen[MC_bze] = 2;    mnxlen[MC_bnz] = 2;    mnxlen[MC_bpz] = 2;    mnxlen[MC_bng] = 2;    mnxlen[MC_bcc] = 2;    mnxlen[MC_bcs] = 2;    mnxlen[MC_jsr] = 2;}MC_bytes MCopcode(char *str)/* query the opcode for string str *//* return the appopriated opcode if opcode exists, else return MC_bad */{    int i;    MC_bytes l;    for (i = 0; str[i]; i++)	str[i] = toupper(str[i]);    l = MC_nop;    while (l <= MAXINSTUCTION && strcmp(str, mnemonics[l]))	l++;    if (l <= MAXINSTUCTION)	return l;    else	return MC_bad;}void newsuffix(char *oldstr, char *ext, char *newstr)/* convert the string oldstr which resemble PRIMARY.xxx to PRIMARY.ext, and save to newstr */{    int i;    char old[256];    strcpy(old, oldstr);    i = strlen(old);    while ((i > 0) && (old[i - 1] != '.') && (old[i - 1] != pathsep))	i--;    if ((i > 0) && (old[i - 1] == '.'))	old[i - 1] = 0;    if (ext[0] != '.') {	strcat(old, ".");    }    strcat(old, ext);    strcpy(newstr, old);}/* #define DEBUG *//*  assemble 2 pass scan for source file , convert the source to machine code*/void ASassemble(bool * errors){    MC_bytes op;    MC_bytes lc = 0;		/* address counter for assembling */    int number;    char ch;    bool okay;    tokentype tokencat;		/* token's category */    int labelidx;		/* indicate the order in symbol table */    char words[10];    char tpwords[15];    MC_opcodes opcode;    int i;    int errpass1 = 0;    FILE *bin;    char binfile[256];    logo();    printf("Assembling code ... \n");    mksymtab(&errpass1);	/* for the 1st pass scan to make symbol table */    fclose(src);    src = NULL;			/* close source file ,prepare for the 2nd pass scan */    if (errpass1 > 0) {	printf("Pass1: totally %d errors found.\n", errpass1);	*errors = errpass1;	return;    }    src = fopen(srcfile, "r");	/* reopen the source file to scan again */    if (src == NULL) {	printf("Could not open input file\n");	return;    }    for (i = 0; i <= MEMSIZE - 1; i++)	/* fill memory with MC_bad */	mem[i] = MC_bad;    lc = 0;			/* clear address counter */    errors = false;		/* errors is for save the state of 2nd pass scan */    /*        source file scan again , by referencing the symbol table which constructed in        the 1st pass scan, it converts the source .asm to machine code and save to mem        */    while (!feof(src)) {	tokencat = ASlex(words, &opcode);	/* read a word, and then identify its cat */	switch (tokencat) {	case ASMCODE:		/* the word read is an assembly instruction */	    op = MCopcode(words);	/* to get its opcode */	    if (op == MC_bad) {	/* no such assembly instruction defined ,raise alarm */		printf("Pass2: %s - Bad mnemonic at %d\n", words, lc);		*errors = true;	    }	    mem[lc] = op;	/* save the legal opcode to memory */	    lc = (lc + 1) % MEMSIZE;	/* address counter indicates the next position */	    break;	case REFLABEL:		/* the word just read is an reference to a label */	    strcpy(tpwords, words);	    strcat(tpwords, ":");	/* make its tail following a ":" for querying symbol table */	    /* seek the label in symbol table to determine its index in symbol table */	    labelidx = seeklabel(tpwords, 1);	    if (labelidx == -1) {		printf		    ("Pass2: ERROR! No such label to be referenced :%s at %d\n",		     words, lc);		*errors = true;		return;		/* no such label defined , invalid reference */	    } else {		mem[lc] = symtabhdr[labelidx].symaddr;/* get the label's address and save it to mem */		lc = (lc + 1) % MEMSIZE;	/* address counter indicates the next mem */	    }	    break;	case NUM:		/* a numeric string got, attention: only 1 byte's width of integer */	    number = atoi(words);	    if (number >= 0)	/* convert to proper byte value */		mem[lc] = number % 256;	    else		mem[lc] = (256 - abs(number) % 256) % 256;	    lc = (lc + 1) % 256;	/* address counter indicates the next mem */	    break;	}    }    binlen = lc;		/* how many bytes we've assembled */    printf("Binary assembled: %d bytes.\n", lc);    fclose(src);    /* dump binary file for reference */    newsuffix(srcfile, "lst", binfile);    bin = fopen(binfile, "a");	/* create a new file named binfile */    if (bin == NULL) {	printf("Binary file ignored.\n");    } else {	char tp[50];	int j = 0;	for (i = 0; i < binlen; i++)	    if (strcmp(getmns(mem[i]), "???")		&& getmnxlen(mem[i]) == 2) {	/* for dealing with 2 bytes instruction */		sprintf(tp, " %02X  %02X%02X      %-4s %02X\n", i,			mem[i], mem[i + 1], getmns(mem[i]), mem[i + 1]);		while (*(tp + j)) {		    fputc(*(tp + j), bin);	/* write to disk file */		    printf("%c", *(tp + j));	/* put to screen */		    j++;		}		j = 0;		i++;	    } else {		/* the instruction only has 1 byte */		sprintf(tp, " %02X  %02X        %-4s\n", i, mem[i],			getmns(mem[i]));		while (*(tp + j)) {		    fputc(*(tp + j), bin);	/* write to disk file */		    printf("%c", *(tp + j));	/* put to screen */		    j++;		}		j = 0;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -