【问题标题】:Write MIPS (32) assembly code to swap the contents of A[2] with B[2]编写 MIPS (32) 汇编代码,将 A[2] 的内容与 B[2] 交换
【发布时间】:2021-09-21 01:13:45
【问题描述】:

这是作业问题:假设寄存器 $s2 保存数组“A”内存中的基地址,寄存器 $s3 保存数组“B”内存中的基地址。编写 MIPS 代码将 A[2] 的内容与 B[2] 交换。

为了澄清,我们只学过 I 型和 R 型指令,我们只知道基本的 sw、lw、加法和减法,没有更复杂的了。我不确定我是否正确理解 lw 和 sw。这是我的尝试:

    lw $t2, 8($s2)      #load A[2] into temp
    lw 8($s2), 8($s3)   #load B[2] into previous A[2], or is lw 8($s2), 8($s3) not allowed?
    sw $t2, 8($s3)      #store previous A[2] value into previous B[2], sw is reversed of lw right?

Here's another 有点类似的问题,不同之处在于它是 A[4] 和 A[9] 在同一个数组中,明显的错误是假设 32 位缺少 4 位缩放,所以 16 不是 4 和 36 不是9. 但对我来说这更优雅,这是汇编交换的正确语法吗?它们还存储在一个临时文件中。

lw $t0, 4($s1) 
sw 4($s1), 9($s1)
sw 9($s1), $t0

他们给出的答案是这样,但我仍然想知道三个陈述答案中的一个是否有效,它不是直接的交换,但我仍然可以这样做:

  lw $t0, 16($s1)
  lw $t1, 36($s1)
  sw $t0, 36($s1)
  sw $t1, 16($s1)

【问题讨论】:

  • lw 和 sw 都不接受两个内存操作数。不会是“负载”或“商店”吗? Load 总是从内存中读取到寄存器中,而 store 则将寄存器的内容写入到内存中。不幸的是,您的解决方案无效。使用汇编程序或查阅指令集参考可以确认这一点。
  • 谢谢,我真的可以使用汇编IDE,我的教授建议SPIM,我有qtSpim,但它似乎不允许输入,我不确定我是否有错误的东西? @小丑
  • QtSpim 允许输入。您需要使用控制台窗口。
  • 我试过了,但也许它不像现代编辑器那样工作,我回去看看能不能解决,谢谢!
  • MARS 在某些方面更好,并且在 x86 上模拟了与 SPIM 相同类型的机器(相同的玩具系统调用,相同的默认小端 MIPS,没有分支延迟槽),并且相同的 asm 语法(旧式 MIPS,与 MIPS 的 GAS / clang 语法的语义不太一样,例如 .align 很奇怪)。 IIRC、qtSPIM 的内置编辑器和保存/构建/调试周期有点笨拙。顺便说一句,Jester 是在谈论用于运行代码的文本 I/O,而不是在编辑器的 IDE 中“输入代码”。我想qtSPIM有一个编辑器,但我忘记了。

标签: arrays assembly mips swap


【解决方案1】:

看起来 sw 和 lw 不能有两个内存操作数,这就是为什么像 lw 8($s2), 8($s3) 这样的东西不起作用!这是最好的答案,这次解释了为什么它不起作用:

  lw $t0, 8($s2)    #load A[2] into temp
  lw $t1, 8($s3)    #load B[2] into temp
  sw $t0, 8($s3)    #store value of A[2] into B[2]
  sw $t1, 8($s2)    #store value of B[2] into A[2]

【讨论】:

  • lw 和 sw 需要寄存器操作数的一个原因是它们的机器代码使用 I 型编码,只有一个立即字段并且没有位来指示加载目标或存储源是寄存器还是记忆。另一个更根本的原因是 MIPS 是一个 RISC,设计为流水线 (en.wikipedia.org/wiki/Classic_RISC_pipeline),而不是具有复杂单指令的 CISC。只有少数像 m68k 或 VAX 这样的 CISC 可以在一条指令中使用两种任意寻址模式进行 mem-to-mem 复制; x86 也无法对其进行编码。
  • 谢谢!现在我想起来了,我被告知 I-type 只有两个寄存器,我必须假设两个寄存器意味着可能存在交换,但这是对 load-destination 和 store-source 工作方式的误解跨度>
  • 是的,这里的问题不是对两个寄存器号进行编码,而是您仍然需要能够加载到寄存器中,因此对于 mem->mem 副本需要单独的操作码. (这可能会将它的 I 型立即数拆分为两个 8 位位移,因为请记住您想要 8(reg) 和 8(reg),如果您总是有,这样的指令不会很有用> 使用两个寄存器的相同立即位移。
  • 但是,更根本的问题是它如何(不)流水线; MIPS 我什至有一个加载延迟槽(即使在 next 指令中也不能使用加载结果,更不用说同一个)。并且两种寻址模式都需要同时进行地址计算。因此,即使您将 CISC mem-mem 副本的编码添加到 MIPS ISA,它也会与 MIPS 设计的全部要点背道而驰(即通过简单的有序设计轻松流水线化,而无需解码像现代 x86 CPU 那样对多个“微操作”(uops)的指令。)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-09-01
  • 2019-08-03
  • 2013-11-21
  • 1970-01-01
  • 2017-12-20
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多