【问题标题】:Convert C to MIPS - Nested Arrays将 C 转换为 MIPS - 嵌套数组
【发布时间】:2011-11-30 05:28:37
【问题描述】:

我正在研究 MIPS 汇编语言,并在书中遇到了这个例子,对我来说这似乎是不正确的。如果是这样,那将不是我在这本书中发现的第一个错误。

变量fg分别分配给寄存器$s0$s1,数组AB的基地址分别是$s6$s7

c代码示例为:

f = g - A[B[4]];

而提供的相应MIPS程序集是:

lw  $t0, 16($s7)
lw  $s0, 0($t0)
sub $s0, $s1, $s0

据我了解,上述 MIPS 代码会从内存中的$t0 提供的地址加载一些随机数据,然后从$s1 中减去它,而不访问$s6 中表示的数组的索引$t0

根据我的理解,正确的 MIPS 程序集应该是:

lw  $t0, 4($s7)
add $t0, $t0, $s6
sll $t0, $t0, 2
lw  $s0, 0($t0)
sub $s0, $s1, $s0

我是正确的,这是书中的错误还是我误解了什么。


编辑:修复了 Chris Dodd 指出的更正 mips 代码中的错误

【问题讨论】:

  • 我认为你是对的。干得好!
  • 你的解释很好。该代码没有做它应该做的事实的最大证据是,没有提到$s6,所以它不可能从数组A中检索一个元素。
  • 假设数组 A 是每个元素 4 个字节(数组 B 似乎是 - 您使用 16 的偏移量来获取元素 4,并使用 lw 指令来获取 4 个字节),您还需要在此处添加乘以 4(或等效移位 2)
  • 很好,克里斯·多德,错过了。
  • 正确。书中的代码充其量是未定义的,最坏的情况是产生段错误。

标签: c assembly mips


【解决方案1】:

这适用于任何可能偶然发现此内容并寻找一个好例子的人(可能是 CprE 381 学生)。 OP的编辑代码仍然不正确。第一个加载字函数中的偏移量应为 16。如果内存宽度为 32 位,则可能为 4,但不需要移位/乘法。假设存储器为 8 位宽,则需要切换加法和移位功能。在 OP 的代码中,它将 A[B[4] / 4] 的地址乘以 4。首先移位/乘法将得到正确的索引。正确的代码是:

lw  $t0, 16($s7)   # gets the value of B[4]
                   # offset could be 4 depending on memory width
                   # but then the shift would not be needed
sll $t0, $t0, 2    # this multiplies the index by 4 to get the address offset
add $t0, $t0, $s6  # adds the base address of A and the offset
lw  $t0, 0($t0)    # loads the value at the address
sub $s0, $s1, $t0  # performs subtraction and stores in f

如果有人对 16 对 4 的整个偏移量以及是否需要移位感到困惑,让我解释一下。如果内存宽度为 32 位,则整个 32 位整数可以存储在一个内存位置。如果是这种情况,则数组索引与地址偏移量相同。但是,如果内存只有 8 位(1 字节)宽,则 32 位整数将存储在 4 个内存位置(每个字节 1 个地址)中。这就是为什么您需要将索引移动 2(或乘以 4)以获得正确的地址偏移量。

【讨论】:

    【解决方案2】:

    正如我的许多人指出的那样,书中有一个错误。自从发现这个错误我发现了几个这样的错误。

    【讨论】:

      【解决方案3】:

      但很可能是作者在链接时间之前复制了代码。这将留下链接器填充 A[] 的内存地址来代替语句中的 0 的可能性

        lw  $s0, 0($t0)
      

      在最终的可执行文件中。我不知道 MIPS 是否允许该大小的偏移量(即最终放置 A[] 的地址范围)。这当然不是在书中解释某事的好方法,默默地打破自己的前提,通常不知道发生了什么。

      【讨论】:

      • 这不起作用,因为偏移量是有符号的 16 位字节偏移量,$s6 原则上可以使用完整的 32 位地址范围。它更有可能只是书中的一个错误。 (另外我认为任何 MIPS 链接器都不会做这种优化,因为相对偏移量真的很讨厌,并且必须处理偏移量太大的情况)
      • 没有理智的汇编器/链接器会这样做。该指令的作用绝对没有混淆。这是带有 reg+imm 地址的显式加载。它不像 HLL 的编译器可以插入任何它想要的指令。
      猜你喜欢
      • 2012-06-16
      • 1970-01-01
      • 2021-10-03
      • 2013-09-28
      • 2020-10-06
      • 1970-01-01
      • 1970-01-01
      • 2021-04-06
      • 1970-01-01
      相关资源
      最近更新 更多