【问题标题】:Converting C array accesses to MIPS将 C 数组访问转换为 MIPS
【发布时间】:2021-06-11 08:59:33
【问题描述】:

问题是:

假设数组AB的基地址分别在寄存器$s6$s7中。

并且变量fg分别被赋值给寄存器$s0$s1

以下C代码对应的MIPS汇编代码是什么:f = g - A[B[4]];

我的想法是:

lw $t0, 16($s7) # $t0 = B[4]
lw $t1, 64($s6) # $t1 = A[B[4]]
sub $s0, $s1, $t1 # $s0 = $s1 - $t1

这个答案我错了,我不知道为什么。有人可以帮我提供一个想法或解释吗?

【问题讨论】:

  • A[B[4]] 意味着$t0 加载结果是此加载地址的一部分。但事实并非如此。

标签: arrays assembly mips


【解决方案1】:

很好的尝试,但您的代码不正确,因为 $t0 已加载但从未使用过。我也不确定数字 64 是从哪里来的,但基本上应该是从B[4]$t0 中提取的值。

您可能对嵌套数组访问A[B[4]] 感到困惑。从概念上讲,这是使用存储在B[4] 中的值作为A 的索引。最好将其扩展并从每行单个操作的 C 代码开始:

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

现在更容易想出:

lw $t0, 16($s7)    # B_val = B[4]
sll $t0, $t0, 2    # B_val *= 4
addu $t2, $t0, $s6 # A_offset = B_val + A_base
lw $t1, ($t2)      # A_val = A[A_offset]
sub $s0, $s1, $t1  # f = g - A_val

在这里,我假设B 的值需要乘以 4。

您总是可以编写一个程序来验证您的工作(至少,在考试之后):

    .data
A: .word 1, 1, 1, 1, 24
B: .word 1, 1, 1, 1, 4

    .text
main:
    la $s6 A           # A_base
    la $s7 B           # B_base
    li $s1, 42         # g = 42

    lw $t0, 16($s7)    # B_val = B[4]
    sll $t0, $t0, 2    # B_val *= 4
    addu $t2, $t0, $s6 # A_offset = B_val + A_base
    lw $t1, ($t2)      # A_val = A[A_offset]
    sub $s0, $s1, $t1  # f = g - A_val

    li $v0, 1
    move $a0, $s0
    syscall            # => should be 42 - 24 = 18

    li $v0, 10
    syscall

【讨论】:

  • 是的,这或多或少是 C 编译器所做的:godbolt.org/z/bMeaebze1。 (由于问题指定值已经在寄存器中,因此采用 args )。 (假设像您所做的那样,这些是有符号int 的数组。)但请注意,指针数学应该使用addu,而不是add:如果A[] 恰好跨越,您不想陷入有符号溢出地址空间的中间,A + B[4] 改变地址的 MSB。 (您几乎从不需要addsub,除非在您期望没有溢出时进行调试 - C 编译器不使用它们,尽管您可以在这里为signed int -
猜你喜欢
  • 2012-06-16
  • 2011-11-30
  • 2019-05-13
  • 2013-09-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多