计算机体系结构:使用 MIPS 交换变量

Computer Architecture : swapping variables with MIPS

我错过了这个话题的class,因为我在国外,没能拿到笔记。你能引导我朝着正确的方向解决这个问题吗?自从我使用 MIPS 以来已经有一段时间了,所以它对我来说基本上是一门外语 :D

家庭作业问题:

MIPS 架构支持字节和半字(16 位)内存传输操作。指令是加载字节 (lb)、加载无符号字节 (lbu)、存储字节 (sb)、加载半字 (lh)、加载无符号半字 (lhu) 和存储半字 (sh)。

代码: 字符 a, b; // 8 位变量 (a@address 100) (b@address 200)

a) 部分假设支持 8 位运算(lb、lbu、sb),编写交换变量的代码。

Part b) 如果MIPS不支持byte和halfword操作,那么我们只能使用‘load word’(lw)和‘store word’(sw),它们是32位操作。因此,仅使用 (lw, sw) 作为内存传输指令重写上面的代码。

注:我真的不是找你帮我解决,我只是不知道该怎么办。我是用 C 编写交换函数然后转换为 MIPS,还是让它过于复杂?谢谢!

首先编写 C 代码并将其用作 mips 程序集的伪代码是执行此操作的好方法。

然后,将 C 代码缩减为我所说的 "simple C"。没有 whilefor 或复杂的表达式。没有局部变量。只有全局变量是您用 .word 定义的东西,例如 myvar: .word 23 或对应于 mips 寄存器的变量。只是很简单if (expr) goto label;

示例见我的回答:Struggling with the logic in if statement

在这里查看我的回答:这也有一堆关于如何编写干净的 asm 代码的技巧和如何使用 C/pseudo 代码构造 asm 代码的示例。

因此,对于 a 部分,我们正在讨论 unsigned char。一旦将值提取到寄存器变量中,应用您将在 C 中执行的标准交换。

对于 b 部分,请注意地址 对齐 到 4 字节边界,因此您可以 fetch/store 它们具有 32 位访问权限。所以,我们正在谈论 unsigned int。皱纹是当交换完成时,必须完成适当的 masking/shifting/splitting 来交换字节,但 而不是 交换剩余的 32 位字,仅使用 unsigned int

那么,先写C代码吧。您可以使用以下方法伪造 100/200:

typedef union {
    unsigned int ival;
    unsigned char bval[4];
} membuf_t;

membuf_t adr100;
membuf_t adr200;

这只是为了让你写真正的 C代码并先测试一下。对于 asm,您可以只引用 [hardwired] 地址(例如 0x100($zero))。

但是,100/200 假定您只是将此作为一个思想实验来做,而不是尝试使用像 [=21 这样的模拟器实际调试您的 asm 代码=] 或 spim [因为他们 真的 不喜欢你在他们模拟的代码中使用这些内存地址。

如果是我,我会使用 mars 并编写可以单步执行的代码。为此,再次稍微调整一下:

adr100:     .word   0x01020304
adr200:     .word   0x05060708

然后,在一切正常后,只需手动替换adr*引用即可。


更新:

有一件事我忘了提,你必须注意字节序问题。也就是说,对于 C 代码,当您从 adrXXX.ival 中获取 32 位时,adrXXX.bval[0] 是第 0-7 位(小端)还是第 24-31 位(大端)?

假设您在 x86 PC 上执行 C 代码,它是小端。 IIRC,mips 也是小端,但是老实说,我忘记了 [有些模型可以是大端或者可以动态切换]。模拟器 [probably] little endian,所以,也许,不用担心。

在 mips(或 C)上进行测试的一种方法是使用额外的测试单元(即创建一个 3-4 行一次性测试程序):test: .word 0。得到一个填充了 0x00000001 的寄存器。然后,将字节存储到 test。然后从 test 加载 32 位。寄存器中的非零字节为您提供机器的字节序(即它在位 0-7 或位 24-31 中)。