【问题标题】:Access register who's number is stored in another register访问寄存器谁的号码存储在另一个寄存器中
【发布时间】:2016-04-10 18:27:21
【问题描述】:

我正在为我的一个课程开发一个项目,该项目涉及将 C 代码转换为 MIPS 程序集。我无法翻译这段代码:

r[extract(ir,15,11)] = aluout;

基本上,r[] 是一个数组,表示 C 中的寄存器。如您所见,它根据 extract 函数的结果确定要访问的寄存器。 MIPS中有这样的东西吗?我能想到的唯一方法是获取我将从提取子例程返回的值,并根据所有寄存器号检查它。其 C 表示形式如下:

regNum = extract(ir, 15, 11);
if (regNum == 1) {
    r[1] = aluout;
} else if (regNum == 2) {
    r[2] = aluout;
} else if (regNum == 3) {
    r[3] = aluout;
} ...

有什么想法吗?这是唯一的方法吗?

【问题讨论】:

  • 嗯,你可以索引一个数组。但是你不能索引原始寄存器。
  • 是的,我知道。 C 代码是我们的教授给我们的,我们应该翻译成 MIPS。 r[index] 仅代表寄存器 $[index] 如果您要将其转换为 MIPS
  • 所以你正在编写一个 MIPS 汇编程序,它应该模拟一个(MIPS?)CPU。我只是将模拟寄存器保存在一个数组中,就像使用 C 一样。您可能无法将所有模拟寄存器保存在真实寄存器中,因为您的程序中需要一些真实寄存器来存储其他内容。
  • 您可以使用跳转表,而不是检查所有数字;在某处拥有所有 32 条可能的指令并跳转到正确的指令。我猜你也可以使用自修改代码来做到这一点。

标签: assembly mips cpu-registers


【解决方案1】:

您应该使用自修改代码吗?例如将寄存器号放入即将运行的指令中?

这个问题更类似于在 C 中具有多个命名变量(var1var2 等)并且必须在 var i 中返回值。如果i 是编译时常量,您可以使用预处理器来完成:

#define expandvar(x) var ## x   // two step process to macro-expand x before concat
#define var(x) expandvar(x)
#define wantvar  4

int foo(void) { return var(wantvar); }
// int foo(constexpr int i) { ... }  // nope

否则你需要一个switch(),你可以随心所欲地实现它(跳转表、分支树或其他任何东西。)

寄存器没有间接级别,除非您将它们全部存储到内存中,然后在该数组中使用变量偏移量。

实现这一点的一种方法是使用计算跳转,而不是使用跳转地址表。你会有一系列的

# calculate $t0 = set_r0 + reg_num * 8.  (probably using PC as the starting point, rather than actually referencing the address of set_r0)
j $t0     # jump to one of the pairs.

set_r0:
    move $r0, src
    j end
    move $r1, src
    j end
    ...

如果您想检索一个寄存器的值,但要破坏所有其他寄存器,

    move $r30, $r31
    move $r29, $r30
    move $r28, $r29
    ...
    move $r0, $r1

在你想要的 reg 被读取的地方跳进去。

【讨论】:

    猜你喜欢
    • 2016-10-28
    • 1970-01-01
    • 2015-07-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多