编写一个高效的RISC-V汇编程序,写入寄存器x3 数字 x4 注册 x7 数字 0,而不更改其他 x7 数字。
示例:
。x3 = 0xdeadbeef, x4 = 0x00000005, x7 = 0xc001cafe
结果:。x7 = 0xc001cafa
仅使用 RISC-V I 级指令集中的指令(讲义中)。 一页名称和编码快速参考表)
我只是在努力理解整个装配。如果有人可以一步一步解释如何解决这个问题,任何帮助将不胜感激
你必须将问题分解为可管理的步骤。
第一个分解是将其写为 C 或伪代码中的表达式。 您将需要一种算法来复制位,尽管非常简单。
以下是我们拥有的一些能力:
我们知道我们可以通过移位来移动位 - 进一步我们可以将输入(例如,
X
)移动恒定量或可变量(例如,Y
) - 所以X >> 2
或X >> Y
。
我们可以通过屏蔽(
and
即&操作)保留一些位并消除其他位。 因此,如果我们想保留某个数字的低两位(例如 Z
),我们可以这样做 Z & 3
。 (请注意,3 是 0...0112,因此 and
与 3 会清除所有高位并仅保留低两位。)
我们可以使用
or
(|
) 操作组合来自两个源的位。 因此,如果我们有两个输入,例如 P
和 Q
,那么 P | Q
代表两者中的所有 1 位。
这些单独的功能中的每一个都可以在大约 1 条装配线中完成。
使用上述功能,我们可以生成一个以您的输入 X、输入位数 Y 和第三个输入 Z 开头的输出。因此,这是使用这些功能创建此表达式的第一步。 请注意,有几个可能的答案,因为我们不必按照上面显示的顺序执行这些功能。
执行此操作的表达式将隔离第一个源中感兴趣的位,将它们移动到适当的位置进行组合(反之亦然),然后隔离第二个源中除感兴趣的位之外的所有位(例如,擦除来自我们想要从第一个输入传输位的第二个源),最后将这些中间体组合成感兴趣的输出。
一旦你有了一个表示你想要看到的结果的表达式,我们可能会将其转换为三地址代码,这是一种将较大的表达式分解为通过变量连接的多个更简单的表达式的方法。
这看起来像几行
TargetN = InputA Operation InputB
。 在三地址代码中,我们总是为每一行的目标选择一个新变量。
三地址代码行将相当简单直接地转换为汇编。 汇编的区别在于,我们将使用寄存器名称(在大多数现代体系结构上)而不是变量名称。 此外,另一个区别是,虽然三地址代码将始终使用新的变量名称作为表示复杂表达式的每行代码的赋值目标,但在汇编中我们可以重用不再保存以后感兴趣的值的寄存器。