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

📄 hmdlg.cpp

📁 本软件实现了汇编语言级虚拟机的模拟
💻 CPP
📖 第 1 页 / 共 3 页
字号:
cds = lookupcmd(cmds); //查询汇编指令表 
opcode = (MC_opcodes) cds; 
// 如果没有查找到相应地汇编指令并且这个符号后面紧跟着":",那么就是地址标号地定义 
if (cds == MAXINSTUCTION && words[strlen(words) - 1] == ':') 
tks = LABEL; // 确定为地址标号的定义 
// 如果没有查找到相应地汇编指令并且这个符号后面没有紧跟着":",那么就是地址标号的引用 
else if (cds == MAXINSTUCTION && words[strlen(words) - 1] != ':') 
tks = REFLABEL; //确定为地址标号的引用 
else 
tks = ASMCODE; // 确定为汇编指令 
    } else if (isdigit(ch)) { // 数字的处理:数字开头后跟0~9的有限序列 
do { 
cmds[i] = ch; 
i++; 
ch = toupper(getc(src)); 
} while (ch > ' ' && isdigit(ch) && !feof(src)); 
tks = NUM; //确定为数字 
cmds[i] = 0; 
strcpy(words, cmds); 
    } else if (ch == ';') { //单行注释:以';'起始至行尾的任意字符序列 
do { 
ch = toupper(getc(src)); 
} while (ch != 0x0a && !feof(src)); 
strcpy(words, "CMNT"); 
opcode = (MC_opcodes) - 99; 
tks = CMNT; //识别为注释字符序列 
    } else { //不可识别的字符的处理 
cmds[i] = ch; 
i++; 
cmds[i] = 0; 
strcpy(words, cmds); 
tks = UNKNOWN; //不可识别的字符 
    } 

    return tks; //返回类别标志 
} 

/*lookupcmd() 
  查询汇编指令表,返回对应的机器指令,机器指令隐含为指令数组的下标 
*/ 
MC_bytes CHMDlg::lookupcmd(char *cmd) 
{ 
    int i = 0; 
    while (i < MAXINSTUCTION && strcmp(getmns(i), cmd)) 
i++; 
    return (MC_bytes) i; 
} 

/* 
  symtablen() 
  取得符号表的长度 
*/ 
int CHMDlg::symtablen() 
{ 
    int i = 0; 
    for (i = 0; i < SYMTABLEN && strcmp(symtabhdr[i].symname, "???????"); i++) 
; 
    return i; 
} 


const int ESC = 1; 

// 将X执行加1操作,并保持其值在0~255范围内,因为CPU字长为8位 
inline void increment(MC_bytes & x) 
{ 
    x = (x + 257) % 256; 
} 

// 将X执行减1操作,并保持其值在0~255范围内,因为CPU字长为8位 
inline void decrement(MC_bytes & x) 
{ 
    x = (x + 255) % 256; 
} 

// 对str所指向的汇编助记符查指令表, 
// 对正确的指令形式返回其所对应的机器码,对于错误的指令返回MC_bad(255) 
MC_bytes CHMDlg::opcoded(char *str) 
{ 
    for (int i = 0; str[i]; i++) 
str[i] = toupper(str[i]); 
    MC_bytes l = MC_nop; 
    while (l <= MAXINSTUCTION && strcmp(str, mnemonics[l])) 
		l++; 
    if (l <= MAXINSTUCTION) 
		return l; 
    else 
		return MC_bad; 
} 

// 以16进制形式输出CPU的256字节内存单元的内容 
void CHMDlg::listcode(char *srcname) 
{ 
    MC_bytes nextbyte = 0, tnb; 
    char filename[256]; 

    newsuffix(srcname, "map", filename); 
    if (*filename == '\0') 
return; 

    FILE *listfile = fopen(filename, "w"); 
    if (listfile == NULL) 
listfile = stdout; 
    for (int i = 1; i <= 16; i++) { 
fprintf(listfile, "%02X(%03d)  ", (i - 1) * 16, (i - 1) * 16); 
tnb = nextbyte; 
int j; 
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); 
} 

// 输出程序运行时错误 
void CHMDlg::runtime_error(MC_bytes pcnow) 
{ 
    switch (ps)
	{ 
    case badop: 
         //fprintf(stdout, "Illegal opcode"); 
         m_show_edit+="\r\n错误的指令:";
		 break; 
    case nodata: 
//fprintf(stdout, "No more data"); 
		m_show_edit+="\r\n指令数据不足:";
		break; 
    case baddata: 
		fprintf(stdout, "Invalid data");
		m_show_edit+="\r\n存在非法数据:"; 
		break; 
    } 
    //fprintf(stdout, " at %d\n", pcnow);
	itoa(pcnow,shh,10);
	m_show_edit+=shh;
	showr();
    //printf ("\nRuntime error happend, dumping memory to runtime.err.map ...\n");
	m_show_edit+="\r\n运行时出错,释放内存!";
    listcode("runtime.err.dump"); //dump runtime error to runtime.err.map file 
} 

// 根据寄存器的值设定标志器P和Z的状态  
inline void CHMDlg::setflags(MC_bytes MC_register) 
{ 
    cpu.z = (MC_register == 0); 
    cpu.p = (MC_register <= 127); 
} 

//计算变址地址 X+B 
inline MC_bytes CHMDlg::index(void) 
{ 
    return ((mem[cpu.pc] + cpu.x) % 256); 
} 

//从data文件读入一字符,并检测是否为中断字符 
void CHMDlg::readchar(char &ch, status & ps) 
{ 
	ins.m_input="";
	ins.m_kind="字符";
	while(ins.m_input=="")
	  ins.DoModal();
	   temp=new char[ins.m_input.GetLength() +1];
        strcpy(temp,ins.m_input);
		ch=temp[0];
    if (ch== ESC) 
     ps = finished; 
    if (ch < ' ') 
     ch = ' '; 
} 

// 将ch内的16进制数转换为数值 
int hexdigit(char ch) 
{ 
    char tpch; 
    tpch = ch; 
// 将大于10的字母转换为相应的数字 
    if (isalpha(ch) && (tpch | 0x20 >= 'a' && tpch | 0x20 <= 'f')) 
        return (ch + 10 - 'a'); 
    if (isdigit(ch)) 
        return (ch - '0'); 
    else 
        return (0); 
} 

// 以指定的进制从data文件读入一个数字 格式{+|-}?{digit}* 
int CHMDlg::getnumber(int base, status &ps) 
{ 
    bool negative = false; 
    char ch; 
    int num = 0; 
	ins.m_input="";
	switch(base){
	case 2:
	ins.m_kind="二进制数";
	break;
	case 10:
    ins.m_kind="十进制数";
	break;
	case 16:
	ins.m_kind="十六进制数";
	break;
	}
	while(ins.m_input=="")
	{
	  ins.DoModal();
	}
	 temp=new char[ins.m_input.GetLength() +1];
     strcpy(temp,ins.m_input);
	 int i=-1;
	do { 
          ch=temp[++i];
          
    } while (!(ch > ' ' || ps != running)&&i<=ins.m_input.GetLength()); 
	if (ps == running) { 
		if (i>=ins.m_input.GetLength()) 
			ps = nodata; 
		else { 
			switch (ch)
			{ 
			case '-': 
				negative = true;
				ch=temp[++i]; 
				break; 
			case '+': 
				negative = false; 
				ch=temp[++i];
				break; 
			} 
			if (!isxdigit(ch)) 
				ps = baddata; 
			else { 
				while (isxdigit(ch) && ps == running) { 
					if (hexdigit(ch) < base && num <= (maxint - hexdigit(ch)) / base) 
						num = base * num + hexdigit(ch); 
					else 
						ps = baddata; 
					ch=temp[++i]; 
				} 
			} 
		} 
		if (negative) 
			num = -num; 
		if (num > 0) 
			return num % 256; 
		else 
			return (256 - abs(num) % 256) % 256; //负数以2的补码的形式表示返回 
	} 

	return 0; 
} 

//对虚拟机执行汇编后的机器指令程序的主体函数 
void CHMDlg::execute() 
{ 
    MC_bytes pcnow; // 程序计数器的先前值 
    MC_bytes carry; // 保存进位位的状态 
    MC_bytes number=0;  
	cpu.ir = mem[cpu.pc]; // 从内存中取指令送入指令寄存器 
	pcnow = cpu.pc; // 保存PC的先前值 
	increment(cpu.pc); // PC指向下一条将要执行的指令地址 
	//if (tracing) 
	//trace(pcnow); //若调试,输出全部cpu内部寄存器值 
	switch (cpu.ir)
	{ //根据指令值,转入相应的处理 
	case MC_nop: 
		break; //空操作,直接返回 
	case MC_clra: //累加器A清0 
		cpu.a = 0; 
		break; 
	case MC_clrc: //进位标志器 C 清0 
		cpu.c = false; 
		break; 
	case MC_clrx: //变址寄存器 x 清0 
		cpu.x = 0; 
		break; 
	case MC_cmc: //进位标志器 C 取反 
		cpu.c = !cpu.c; 
		break; 
	case MC_inc: //累加器A自增1,影响标志器 
		increment(cpu.a); 
		setflags(cpu.a); 
		break; 
	case MC_dec: //累加器A自减1,影响标志器 
		decrement(cpu.a); 
		setflags(cpu.a); 
		break; 
	case MC_incx: //变址寄存器 x 自增1,影响标志器 
		increment(cpu.x); 
		setflags(cpu.x); 
		break; 
	case MC_decx: //变址寄存器 x 自减1,影响标志器 
		decrement(cpu.x); 
		setflags(cpu.x); 
		break; 
	case MC_tax: //累加器A内容送入变址寄存器 x 
		cpu.x = cpu.a; 
		break; 
	case MC_ini: //从输入读一10进制数送累加器A,影响标志器 
		cpu.a = getnumber(10, ps); 
		setflags(cpu.a); 
		break; 
	case MC_inb: //从输入读一2进制数送累加器A,影响标志器 
		cpu.a = getnumber(2, ps); 
		setflags(cpu.a); 
		break; 
	case MC_inh: //从输入读一16进制数送累加器A,影响标志器 
		cpu.a = getnumber(16, ps); 
		setflags(cpu.a); 
		break; 
	case MC_ina: //从输入读一ascii字符送累加器A,影响标志器 
		char ascii; 
		readchar(ascii, ps); 
			cpu.a = ascii; 
			setflags(cpu.a); 
		break; 
	case MC_oti: //以10进形式输出累加器A的内容 
		if (cpu.a < 128) 
			itoa(cpu.a,bits,10);
	    else itoa(cpu.a - 256,bits,10); 
		m_out+=bits;
		UpdateData(false);
        break; 
case MC_oth: //以16进形式输出累加器A的内容 
       itoa(cpu.a,bits,16); 
		m_out+=bits;
		UpdateData(false);
		break; 
case MC_otc: //以无符号10进数形式输出累加器A的内容 
	if(cpu.a>=0)
    itoa(cpu.a,bits,10);
	else
    itoa(0-cpu.a,bits,10);
	m_out+=bits;
	UpdateData(false);
	break; 
case MC_otb: //以无符号2进制形式输出累加器A的内容 
   itb(cpu.a);
   m_out+=bits;
   UpdateData(false);
   break; 
case MC_ota: //以ascii字符形式输出累加器A的内容 
   m_out+=cpu.a;
   UpdateData(false);
break; 
case MC_push: //压栈操作:堆栈指针SP减1,累加器A的内容压入栈顶。 
decrement(cpu.sp); 
mem[cpu.sp] = cpu.a; 
break; 
case MC_pop: //出栈操作:栈顶的内容送入A,堆栈指针SP增1,影响标志器 
cpu.a = mem[cpu.sp]; 
cpu.ar=cpu.sp;
increment(cpu.sp); 
setflags(cpu.a); 
break; 
case MC_shl: //累加器A的各位顺次左移1位,最高位移入进位标志C,影响标志器 
cpu.c = (cpu.a * 2 > 255); 
cpu.a = cpu.a * 2 % 256; 
setflags(cpu.a); 
break; 
case MC_shr: //累加器A的各位顺次右移1位,最低位移入进位标志C,影响标志器 
cpu.c = cpu.a & 1; 
cpu.a /= 2; 
setflags(cpu.a); 
break; 
case MC_ret: //子程序调用返回,将栈顶保存的返回地址送PC,退栈 
cpu.pc = mem[cpu.sp]; 
cpu.ar=cpu.sp;
increment(cpu.sp); 
break; 
case MC_halt: //停机 
ps = finished; 
break; 
case MC_lda: 
//双字节指令,格式:LDA B,其第二字节为一个内存地址, 
//将位于B地址单元中的内容送入A累加器. 
//实现时以当前PC所指内存中的数值为地址偏移,将其所指的内存中的内容送入A 
cpu.a = mem[mem[cpu.pc]]; 
cpu.ar=mem[cpu.pc];
increment(cpu.pc); 
setflags(cpu.a); 
break; 
case MC_ldx: 
//将X+B所指的内存单元的内容送入A,即:A=[X+B] 
cpu.a = mem[index()]; 
cpu.ar=index();
increment(cpu.pc); 
setflags(cpu.a); 
break; 
case MC_ldi: //A=ImmB 
cpu.a = mem[cpu.pc]; 
cpu.ar=cpu.pc;
increment(cpu.pc); 
setflags(cpu.a); 
break; 
case MC_lsp: //SP=[ImmB] 
cpu.sp = mem[mem[cpu.pc]];
cpu.ar= mem[cpu.pc];
increment(cpu.pc); 
break; 
case MC_lspi: //SP=ImmB 
cpu.sp = mem[cpu.pc]; 
cpu.ar=cpu.pc;
increment(cpu.pc); 
break; 
case MC_sta: //[ImmB]=A 
mem[mem[cpu.pc]] = cpu.a; 
increment(cpu.pc); 
break; 
case MC_stx: //[X+B]=A 
mem[index()] = cpu.a; 
increment(cpu.pc); 
break; 
case MC_add: //A=A+[ImmB] 
cpu.c = (cpu.a + mem[mem[cpu.pc]] > 255); 
cpu.a = (cpu.a + mem[mem[cpu.pc]]) % 256; //限定数值的大小为8bit 
cpu.ar= mem[cpu.pc];
increment(cpu.pc); 
setflags(cpu.a); 
break; 
case MC_adx: //A=A+[X+ImmB] 
cpu.c = (cpu.a + mem[index()] > 255); 
cpu.a = (cpu.a + mem[index()]) % 256;
cpu.ar=index();
increment(cpu.pc); 
setflags(cpu.a); 
break; 
case MC_adi: //A=A+ImmB 
cpu.c = (cpu.a + mem[cpu.pc] > 255); 
cpu.a = (cpu.a + mem[cpu.pc]) % 256;
cpu.ar=cpu.pc; 
increment(cpu.pc); 
setflags(cpu.a); 
break; 
case MC_adc: //A=A+C+[ImmB] 
carry = cpu.c; 
cpu.c = (cpu.a + mem[mem[cpu.pc]] + carry > 255); 
cpu.a = (cpu.a + mem[mem[cpu.pc]] + carry) % 256; 
cpu.ar= mem[cpu.pc];
increment(cpu.pc); 
setflags(cpu.a); 
break; 
case MC_acx: //A=A+C+[X+ImmB] 
carry = cpu.c; 
cpu.c = (cpu.a + mem[index()] + carry > 255); 
cpu.a = (cpu.a + mem[index()] + carry) % 256; 
cpu.ar= index();
increment(cpu.pc); 
setflags(cpu.a); 
break; 
case MC_aci: //A=A+C+ImmB 
carry = cpu.c; 
cpu.c = (cpu.a + mem[cpu.pc] + carry > 255); 
cpu.a = (cpu.a + mem[cpu.pc] + carry) % 256; 
increment(cpu.pc); 
cpu.ar=cpu.pc;
setflags(cpu.a); 
break; 
case MC_sub: //A=A-[ImmB] 
cpu.c = (cpu.a < mem[mem[cpu.pc]]); 
cpu.a = (cpu.a - mem[mem[cpu.pc]] + 256) % 256; 
cpu.ar= mem[cpu.pc];
increment(cpu.pc); 
setflags(cpu.a); 
break; 
case MC_sbx: //A=A-[X+ImmB] 
cpu.c = (cpu.a < mem[index()]); 
cpu.a = (cpu.a - mem[index()] + 256) % 256;
cpu.ar=index(); 
increment(cpu.pc); 
setflags(cpu.a); 
break; 
case MC_sbi: //A=A-ImmB 
cpu.c = (cpu.a < mem[cpu.pc]); 
cpu.a = (cpu.a - mem[cpu.pc] + 256) % 256; 
cpu.ar=cpu.pc;
increment(cpu.pc); 
setflags(cpu.a); 
break; 
case MC_sbc: //A=A-C-[ImmB] 
carry = cpu.c; 
cpu.c = (cpu.a < mem[mem[cpu.pc]] + carry); 
cpu.a = (cpu.a - mem[mem[cpu.pc]] - carry + 256) % 256; 
cpu.ar= mem[cpu.pc];
increment(cpu.pc); 
setflags(cpu.a); 
break; 
case MC_scx: //A=A-C-[X+ImmB] 
carry = cpu.c; 
cpu.c = (cpu.a < mem[index()] + carry); 
cpu.a = (cpu.a - mem[index()] - carry + 256) % 256; 
cpu.ar= index();
increment(cpu.pc); 
setflags(cpu.a); 
break; 
case MC_sci: //A=A-C-ImmB 
carry = cpu.c; 
cpu.c = (cpu.a < mem[cpu.pc] + carry); 
cpu.a = (cpu.a - mem[cpu.pc] - carry + 256) % 256;
cpu.ar=cpu.pc; 
increment(cpu.pc); 
setflags(cpu.a); 
break; 
case MC_cmp: //A与B所指单元的内容进行比较,影响标志位 
cpu.c = (cpu.a < mem[mem[cpu.pc]]); 
setflags((cpu.a - mem[mem[cpu.pc]] + 256) % 256); 
cpu.ar= mem[cpu.pc];
increment(cpu.pc); 
break; 
case MC_cpx: //A与 X+ImmB 所指单元的内容进行比较,影响标志位 
cpu.c = (cpu.a < mem[index()]); 
setflags((cpu.a - mem[index()] + 256) % 256); 
cpu.ar=index();
increment(cpu.pc); 
break; 
case MC_cpi: //A与ImmB进行比较,影响标志位 
cpu.c = (cpu.a < mem[cpu.pc]);
cpu.ar=cpu.pc; 
setflags((cpu.a - mem[cpu.pc] + 256) % 256); 
increment(cpu.pc); 
break; 
case MC_ana: //A与[ImmB]进行位与,影响标志位 
cpu.a &= mem[mem[cpu.pc]]; 
cpu.ar= mem[cpu.pc];
increment(cpu.pc); 
setflags(cpu.a); 
cpu.c = false; 
break; 
case MC_anx: //A与[X+ImmB]进行位与,影响标志位 
cpu.a &= mem[index()]; 
cpu.ar=index();
increment(cpu.pc); 
setflags(cpu.a); 
cpu.c = false; 
break; 
case MC_ani: //A与ImmB进行位与,影响标志位 
cpu.a &= mem[cpu.pc];
cpu.ar=cpu.pc; 
increment(cpu.pc); 
setflags(cpu.a); 
cpu.c = false; 

⌨️ 快捷键说明

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