MIP:我在向后穿越阵列时做错了什么

发布于 2025-02-06 04:46:19 字数 400 浏览 2 评论 0原文

我的指示找不到缺陷。在指令2中,我将[19] + 4放入注册$ T1中。

有问题

”

I cant find a flaw in my instructions. In instruction 2, I am putting A[19] + 4 into register $t1.

Something is wrong

Screen-Shot-2022-06-09-at-5-15-17-PM.png

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

沩ん囻菔务 2025-02-13 04:46:19

这项任务非常棘手。我认为,如果您想一次访问每个元素,则将使用该循环结构与该数量的指令使用的唯一方法是从-4($ T1)加载。

这意味着当ptr ==& a [0]是正确的(beq $ t1,$ s0,exit)时退出[-1] 最后迭代。

这也避免了从a [n],一past-the-end,一个错误中加载的问题。

但是我不会将t1描述为“当前地址”;这是您要访问此迭代的元素的地址 + 4。但是,这种循环结构在顶部有条件分支效率低下,而不是您要记住的模式。

通常,您想安排东西,以便底部有一个有条件的分支,回到环的顶部或掉落。您不需要j loop if()折断在身体内部,即使可以通过旋转环将条件放在底部的情况下,也可以避免它这意味着在开始或结束时剥离几个说明。

例如:

在这种情况下,有效编写此此内容的正常方法将为
endp = arr+n;; for(p = arr; p!= endp; p ++)...

   or     $s1, $zero, $zero  # sum=0:  move $s1, $zero
## for variable n, check that it's non-zero like beqz $n, skip_loop
   or     $t1, $s0, $zero    # p = A;  move $t1, $t0
   addiu  $t2, $s0, 80       # endp = A + n
LOOP:                        # do{
    lw     $t0, 0($t1)
    addiu  $t1, $t1, 4
    add    $s1, $s1, $t0        # sum += *p++  with trapping on signed overflow 
    bne    $t1, $t2, LOOP    # }while(p != endp)

在循环外的另一项指令,需要另外一个寄存器。除非您不需要a的基本地址,否则您可以将$ s1而不是先复制。

但这是循环中较少的说明,因此N> = 1和相同的静态代码大小的指令执行。 (或者如果我们可以破坏指针)。

MIPS具有寄存器的 ,因此使用一个额外的寄存器通常不是问题。而且,除非您的循环只跑一对夫妇,否则在循环中花费额外的指示以使用较少的寄存器是错误的经济。条件分支不在底部的循环很愚蠢,尤其是当容易确保它们至少运行1次迭代时,并且情况很简单时,以便更有效地写入它时。

另外,我安排了指令,以不使用加载后立即使用负载结果!不必要地停滞不前。 MIPS II,后来使这样做是安全的,但仍会停滞不前。指针增量是加载后立即完成的完美之处。 (在带有分支延迟插槽的真实MIPS上,您将添加$ s1,$ s1,$ t0 < / code>添加到分支延迟插槽中,因此它的load / p ++ / bne / sum+=。)

This assignment is pretty tricky. I think the only way to use that loop structure with that number of instructions is to load from -4($t1), if you want to access every element once.

That means exiting when ptr == &A[0] is correct (beq $t1, $s0, EXIT), since you already accessed it as ptr[-1] last iteration.

That also avoids the problem of loading from A[n], one-past-the-end, a bug in your current code.

But I wouldn't describe t1 as "the current address"; it's the address + 4 of the element you're going to access this iteration. But this loop structure with a conditional branch at the top is inefficient anyway, not a pattern you'd want to memorize.

Normally you want to arrange things so there's a conditional branch at the bottom, going back to the top of the loop or falling through. You don't want a j LOOP with an if () break inside the body if you can avoid it by rotating the loop to put the condition at the bottom, even if that means peeling a couple instructions at the start or end.

For example:

In this case, the normal way to write this efficiently would be
endp = arr+n; ; for(p = arr ; p != endp ; p++) ...

   or     $s1, $zero, $zero  # sum=0:  move $s1, $zero
## for variable n, check that it's non-zero like beqz $n, skip_loop
   or     $t1, $s0, $zero    # p = A;  move $t1, $t0
   addiu  $t2, $s0, 80       # endp = A + n
LOOP:                        # do{
    lw     $t0, 0($t1)
    addiu  $t1, $t1, 4
    add    $s1, $s1, $t0        # sum += *p++  with trapping on signed overflow 
    bne    $t1, $t2, LOOP    # }while(p != endp)

One more instruction outside the loop, and one more register needed. Unless you don't need the base address of A after the loop, then you can just increment $s1 instead of copying it first.

But this is fewer instructions in the loop, so fewer instructions executed for n>=1, and same static code size. (Or smaller if we can destroy the pointer).

MIPS has lots of registers, so using one extra is usually not a problem. And unless your loop runs only a couple, spending an extra instruction inside the loop to use fewer registers is a false economy. Loops with the conditional branch not at the bottom are dumb, especially when it's easy to be sure they run at least 1 iteration, and when the condition is simple so it's easy to write it the more efficient way.

Also, I scheduled my instructions to not use the load result right after the load! No sense stalling an in-order pipeline unnecessarily. MIPS II and later made it safe to do that for correctness, but would still stall. A pointer increment is the perfect thing to do right after a load. (On a real MIPS with a branch delay slot, you'd reorder the add $s1, $s1, $t0 into the branch delay slot, so it's load / p++ / bne / sum+=.)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文