MIP:我在向后穿越阵列时做错了什么
I cant find a flaw in my instructions. In instruction 2, I am putting A[19] + 4 into register $t1.
Something is wrong
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
这项任务非常棘手。我认为,如果您想一次访问每个元素,则将使用该循环结构与该数量的指令使用的唯一方法是从
-4($ T1)
加载。这意味着当
ptr ==& a [0]
是正确的(beq $ t1,$ s0,exit
)时退出[-1] 最后迭代。这也避免了从
a [n]
,一past-the-end,一个错误中加载的问题。但是我不会将
t1
描述为“当前地址”;这是您要访问此迭代的元素的地址 + 4。但是,这种循环结构在顶部有条件分支效率低下,而不是您要记住的模式。通常,您想安排东西,以便底部有一个有条件的分支,回到环的顶部或掉落。您不需要
j loop
if()折断
在身体内部,即使可以通过旋转环将条件放在底部的情况下,也可以避免它这意味着在开始或结束时剥离几个说明。例如:
bne reg,reg,reg,loop,loop
。在这种情况下,有效编写此此内容的正常方法将为
endp = arr+n;
;for(p = arr; p!= endp; p ++)...
在循环外的另一项指令,需要另外一个寄存器。除非您不需要
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 asptr[-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 anif () 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:
bne reg,reg, loop
.In this case, the normal way to write this efficiently would be
endp = arr+n;
;for(p = arr ; p != endp ; p++) ...
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+=.)