【问题标题】:Simulating basic machine language in C.用 C 模拟基本机器语言。
【发布时间】:2011-09-16 06:35:21
【问题描述】:

所以对于我的作业,我必须用 C 模拟基本机器语言。这台机器有 16 个寄存器 (reg[])、一个程序计数器 (pc) 和内存 (mem[]),所有这些都是无符号字符。指令是从文件中读入的,格式为:

B404(1RXY = 用内存地址 XY 的值加载寄存器 R)。所有数字都是十六进制的。 C000 是停止命令。

现在我的问题是,当我打印出指令时(当存储在 a、b、c、d 和 cd 中时)b 和 d 有前导零。如何摆脱它们,以便如上打印说明? (第 48 行)。

另外,我的一些 if 语句似乎没有被调用,就好像我在其中放入了 printf() 并且它们位于从未打印过的文件中。 (第 48 到 78 行)。

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

int main () {
FILE *file;
file = fopen("a3.txt","r");
unsigned int temp = 0;
unsigned char pc, mem[256], reg[16],a,b,c,d,cd;
unsigned int count;
count = 0;
pc = 0;
for (int i=0; i < 16;++i) {
    reg[i] = 0;
}

if (file == NULL) {
    printf("\n Error opening the file");
    exit(0);
}
for (int i=0; !feof(file); i += 2) {
    fscanf(file, "%X", &temp);
    mem[i] = ((temp & 0xFF00) >> 8);
    mem[i + 1] = (temp & 0xFF);
    if (feof(file)) {
        break; // exit from while
    }
    ++count;
}
int fclose(FILE *file);
/*while (mem[pc] != 0xC0) {*/
for (unsigned int i=0; i < count-1;++i) {
    if (mem[i] == 0xC0) {
        break; // exit from for
        exit(1);
    }
    cd = mem[pc + 1];
    a = (mem[pc] & 0xF0);
    b = (mem[pc] & 0xF);
    c = (mem[pc + 1] & 0xF0);
    d = (mem[pc + 1] & 0xF);
    printf("%02X ",pc);
    printf("%X%X%X%X - [",a,b,c,d);
    printf("%02X %02X %02X %02X ",reg[0],reg[1],reg[2],reg[3]);
    printf("%02X %02X %02X %02X ",reg[4],reg[5],reg[6],reg[7]);
    printf("%02X %02X %02X %02X ",reg[8],reg[9],reg[10],reg[11]);
    printf("%02X %02X %02X %02X]\n",reg[12],reg[13],reg[14],reg[15]);
    if (a == 0x1) {
        reg[b] = reg[cd];
    }
    if (a == 0x2) {
        reg[b] = cd;
        //printf("2 reporting in");
    }
    if (a == 0x3) {
        reg[cd] = reg[b];
    }
    if (a == 0x4) {
        reg[d] = reg[c];
    }
    if (a == 0x05) {
        reg[d] = (reg[b] + reg[c]);
        //printf("5 reporting in");
    }
    if (a == 0x7) {
        reg[d] = (reg[b] | reg[c]);
    }
    if (a == 0x8) {
        reg[d] = (reg[b] & reg[c]);
    }
    if (a == 0x9) {
        reg[d] = (reg[b] ^ reg[c]);
    }
    if (a == 0xA0) {
        reg[b] = (reg[b] >> reg[d]) | (reg[b] << (32 - reg[d]));
    }
    pc += 2;
    if (a == 0xB0) {
        //printf("B reporting in");
        if (reg[b] == reg[0]) {
            pc = cd;
        }
    }
}
return 0;
}

谢谢!

【问题讨论】:

  • 如果您将之前的问题标记为已回答,您可能会收到更多回复?
  • 这是你的任务 - 它应该由你完成;)
  • 如您所见,我已经尽力做到了。我只是觉得我缺少一些小东西,为什么它没有按我想要的那样工作。
  • 从 Roland 的代码中汲取的一点智慧是函数。功能使世界运转。这是您在 C 中进行抽象的主要方式。main() 应该做的只是在 真正的中心函数 和命令行参数之间进行接口。

标签: c machine-code


【解决方案1】:

要获取无符号字符的高位,请使用以下函数:

unsigned char hi(unsigned char bits) {
  return (bits >> 4) & 0x0F;
}

当你进行指令调度时,最好使用switch 语句而不是if ... else if ... else 级联。然后你可以有一个简单的default: fprintf(stderr, "unknown instruction: %u\n", a); exit(1); 用于错误检测。

另外,0xA0 的值不是 10,而是 160,所以你应该写 100x0A

更新:

提取abcd的代码应如下所示:

a = (mem[pc + 0] >> 4) & 0x0F;
b = (mem[pc + 0] >> 0) & 0x0F;
c = (mem[pc + 1] >> 4) & 0x0F;
d = (mem[pc + 1] >> 0) & 0x0F;

这易于阅读且易于检查正确性。可以清楚地看到统一处理,并且每个值都被限制在[0x00;0x0F]的范围内。

【讨论】:

  • 谢谢!我现在要尝试实现一个 switch 语句。
  • 如果你想知道有经验的程序员如何实现这个任务,这里是:roland-illig.de/tmp/machine.c。但不要考虑提交或复制这个。你可能想比较一下代码,看看我是怎么做的。
猜你喜欢
  • 2013-02-18
  • 2016-08-14
  • 1970-01-01
  • 2017-04-07
  • 2017-11-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多