搞了一个早上,代码有点搓。。。。
由于判断while退出的条件是HLT,而我却画蛇添足加了个PC>32的条件。
导致了几次的Wrong Answer
其实题目很简单,就是实现一些简单的运算罢了,主要还是对题目的理解。
下面是指令的翻译
000xxxxx STA x 把运算器的值存入内存x store the value of the accu into memory byte x
001xxxxx LDA x 从内存地址x载入值到运算器load the value of memory byte x into the accu
010xxxxx BEQ x 如果运算器的值为0,那么载入内存地址x到运算器if the value of the accu is 0 load the value x into the pc
011----- NOP 空操作 no operation
100----- DEC 运算器减1 subtract 1 from the accu
101----- INC 运算器加1 add 1 to the accu
110xxxxx JMP x 载入内存地址到 pc load the value x into the pc
111----- HLT 结束程序 terminate program
学过组成原理的同学都知道,x86机器内存中数据的存放是小顶机模型,也就是lower-to-higher
但是这道题目不同,是higher-to-lower.这个要注意。
#include <stdio.h> #include <string.h> #include <math.h> void getinstructions(char a[], char b[]) { b[0] = a[0]; b[1] = a[1]; b[2] = a[2]; b[3] = '/0'; } void getoperand(char a[], char b[]) { b[0] = a[3]; b[1] = a[4]; b[2] = a[5]; b[3] = a[6]; b[4] = a[7]; b[5] = '/0'; } void convto10(char a[],int lena,int &b,int jinzhi) { int i; b = 0; int c; for (i=0;i<lena;i++) { c = pow(jinzhi, lena-i-1); b += (a[i] - '0')*c; } } void tomem(char a[], int len, char mem[]) { int i,j; for (i=0;i<8-len;i++) mem[i] = '0'; j=0; for (;i<8;i++,j++) mem[i] = a[j]; mem[i] = '/0'; } void conv(int m, int n, char ret[]) { int k,l,i; int arr[50]; int count; count = 0; k=m; while (1) { l = k%n; if (k == 0) break; if (l>=10) arr[count] = 'A'+l-10; else arr[count] = l + '0'; k /= n; count++; } for (i=0;i<count;i++) ret[i] = arr[count-i-1]; ret[i] = '/0'; return; } int main() { char oper[20]; char inst[20]; int jinzhi10; int i; int tmp; char ret[20]; char ret2[20]; char mem[32][20]; int pc; int add; while (scanf("%s", mem[0])!=EOF) { pc = 0; add = 0; for (i=1;i<32;i++) scanf("%s", mem[i]); while (1) { getoperand(mem[pc], oper); getinstructions(mem[pc], inst); //操作数的10进制形式 convto10(oper,5, jinzhi10, 2); //printf("%d %d ", pc, add); if (strncmp(inst, "000", 3) == 0) { //把运算器的值转换为2进制 conv(add, 2, ret); //把二进制的值写入内存 tomem(ret, strlen(ret), mem[jinzhi10]); /* printf("STA/n");*/ } else if (strncmp(inst, "001", 3) == 0) { //把内存地址x的值转换为10进制 convto10(mem[jinzhi10], 8, tmp, 2); //载入运算器 add = tmp; /* printf("LDA/n");*/ } else if (strncmp(inst, "010", 3) == 0) { //如果运算器的值为0 if (add == 0) { //载入运算器 pc = jinzhi10; /* printf("BEQ/n");*/ continue; } /* printf("BEQ/n");*/ } else if (strncmp(inst, "011", 3) == 0) { /* printf("NOP/n");*/ //NOP } else if (strncmp(inst, "100", 3) == 0) { if (add == 0) add = 0xFF; else --add; /* printf("DEC/n");*/ } else if (strncmp(inst, "101", 3) == 0) { add ++; if (add > 255) add = 0; /* printf("INC/n");*/ } else if (strncmp(inst, "110", 3) == 0) { pc = jinzhi10; /* printf("JMP/n");*/ continue; } else if (strncmp(inst, "111", 3) == 0) { /* printf("HLT/n");*/ break; } pc++; pc %=32; } conv(add, 2, ret); tomem(ret, strlen(ret), ret2); printf("%s/n", ret2); } return 0; }
另外加个比较good一些的代码。
这代码主要通过移位运算来做。比我那个字符串处理的简单多了。。。
#define memsize 32 #define EA 0x1F #define opcode 0xE0 #include <stdio.h> typedef unsigned char byte; byte memory[memsize]; byte accu,pc; int main() { int k; while(1) { int j,i; for (j=0;j<memsize;j++) { byte unit=0; char c[9]; if (scanf("%s",c)==EOF) return 0; for (i=0;i<8;i++) { unit*=2; unit+=c[i]-'0'; } memory[j]=unit; } pc=accu=0; while(1) { byte instruction=memory[pc]; pc=(pc+1) % memsize; byte code=(instruction & opcode)>>5; switch (code) { case 0: memory[instruction & EA]=accu; break; case 1: accu=memory[instruction & EA]; break; case 2: if (accu==0) pc=instruction & EA; break; case 3: break; case 4: accu--; break; case 5: accu++; break; case 6: pc=instruction & EA; break; case 7: goto Exit; } } Exit: for (k=0;k<8;k++) { putchar(((accu & 0x80)>>7)+'0'); accu<<=1; } putchar('/n'); } }