【问题标题】:MIPS - How to Convert a set of Integers into Single-Precision FloatsMIPS - 如何将一组整数转换为单精度浮点数
【发布时间】:2013-10-30 05:10:28
【问题描述】:

我真的很难弄清楚如何解决这个问题。我知道我想采用整数和小数的二进制表示,将它们组合为尾数,并将符号位分配到开头,但我不知道如何在 MIPS 中实际实现它。

任何人都可以帮助我至少开始吗?

假设您的 MIPS 硬件没有浮点寄存器和浮点 ALU。如果 你想执行浮点加法,你必须使用 MIPS 整数指令 整数寄存器 ($0 - $31) 和整数 ALU 来完成工作。在这个作业问题中, 您将编写 MIPS 代码,仅使用整数指令和整数寄存器,以实现 过程来添加两个浮点数并编写一个 main 函数来调用该过程。

  1. 编写 MIPS 过程 toFloat 以将浮点数转换为 IEEE 单精度格式。 该过程将三个整数作为输入:$a0、$a1、$a2,它们代表一个浮点数 这样:如果 $a0 包含 0,则浮点数为正数,否则如果 $a0 包含 1,则 浮点数为负数。存储在寄存器 $a1 中的数字是 浮点数,存储在寄存器 $a2 中的数字是浮点数的小数部分 数字。 例如,要显示浮点数 -5.25,三个输入寄存器应包含 这些数字:$a0 = 1、$a1 = 5 和 $a2 = 25。对于小数部分,您可以使用 div rs rt 指令将 25 除以 100。分数将存储在 HI 寄存器中,您可以使用 mfhi 指令来检索分数。 该过程将返回 v0,其中包含对应于 由三个输入数字表示的浮点数。 完成此过程后,您可以使用它将输入的数字 2.5 和 7.5 转换为它们的 IEEE 单精度格式。

  2. 编写 MIPS 过程 printFloat 以打印 IEEE 单精度格式的数字。 过程的输入是 $a0,它是一个 IEEE 单精度格式的数字。这 过程将简单地打印存储在 $a0 中的位模式。您可以使用循环打印每个位。 完成此过程后,您可以使用它以浮点格式打印输入数字 2.57.5

  3. 编写一个 MIPS 程序来实现 main 函数来调用您的程序。在这个节目中,你 会调用

    toFloat(0, 2, 5) 生成 2.5 的浮点格式;

    toFloat(0, 7, 5) 生成 7.5 的浮点格式;

    printFloat 打印 2.5

    printFloat 打印 7.5

这是我目前拥有的代码:

http://s7.postimg.org/v39ufikaj/code.png

【问题讨论】:

  • “只是帮助我开始”有多远?我可以建议使用“sll $t0, $a0, 31”将符号位移动到正确的位置以执行“或 $t1,$t1,$t0”吗?或者您是否需要回答类似“what's a左移和按位或?"
  • 这绝对有帮助。所以很明显,我们通过将符号位移到第一个位置,但我对如何从这些值确定指数和尾数有点困惑。
  • 对于代码 sn-p,您可能会更幸运地发布到 gist.github.com - 从 .png 图像中读取汇编代码有点太痛苦了!

标签: floating-point integer mips mars-simulator single-precision


【解决方案1】:

好的,第一步(如 cmets 中所述)是花一些时间使用显示位的转换器,例如:binaryconvert.com floating point converter

然后,简单的部分是取 $a0 并将位 0 ​​转储到我们结果的位 1 中。比如:

add $v0, $zero, $zero # initialize our result
sll $t0, $a0, 31 # shift the lsb to the msb
or $v0, $v0, $t0 # set the sign bit in the result

但现在我们必须做数学。我希望 $a1 是整数部分,而 $a2 是 binary 小数部分。但事实并非如此......他们说 $a1 是整数(仍然是二进制整数),但 $a2 实际上是美分。 (如果 25/100 = 0.25 十进制,则 $a2 包含美分。)

这就是我自己感到困惑的地方。指令说“使用 div rs rt 指令将 25 除以 100。分数将存储在 HI 寄存器中”。但是当我读到 div 所做的 (MIPS Instruction Reference) 时,它说它将商放在 $LO 中,将 余数 放在 $HI 中。因此,将 25 除以 100 将得到... 25。这是丢弃大于 100 的数量的好方法,但它不会让我们得到数字的二进制小数表示。

事实上,我花了整堂课和午餐时间试图找出一种优雅的方法来取 0 到 99 之间的数字,除以 100,然后在不使用 FPU 的情况下将结果转换为二进制。我来不及了。所以我会让你问教授这部分。

但是,一旦我们在 $a1 中有整数部分,以及代表小数部分的 1 和 0 字符串(让我们把它放在 $s2 中),我们只需要对其进行规范化。我们在$a1.$s2 中有一个号码,我们需要它采用这种格式:

1.nnnnnnn

...我们从 1 开始,然后小数部分是许多二进制数字。

这里有一些可能有效的伪代码。

  • 左移 $a1 直到 msb 为“1”。在 $t0 中存储班次数。 (注意:这里假设整数部分不为零)
  • (31 - $t0) 为您提供指数。通过偏差调整它并填充到浮点结果的 30-23 位。
  • $t0 还告诉您小数位有多少空间。将 $s2 移动适当的量(这取决于它的编码方式),然后 or 它以填充 $a1 的最低有效位
  • $a1 再左移一位,因为在 IEEE FP 中前导的“1”被丢弃
  • 将 $a1 的前 23 位填充到浮点结果的 22-0 位中

让我们看看这是否适用于示例。 $a1 的整数部分为 0x0000C000,$s2 不知何故加载了 0.75 (1 x 2^-1 + 1 x 2^-2)

$a1: 0000 0000 0000 0000 1100 0000 0000 0000 
$s2: 1100 0000 0000 0000 0000 0000 0000 0000

我必须移动 $a1 16 次:

$a1: 1100 0000 0000 0000 0000 0000 0000 0000 

这应该给我一个 31 - 16 = 15 的指数。加上 127 的偏差,我得到 142 (0x8E)。这在指数部分。

我需要将 $s2 右移相同的量 (16):

$s2: 0000 0000 0000 0000 1100 0000 0000 0000

or那些一起:

$a1:  1100 0000 0000 0000 1100 0000 0000 0000

用小数点可视化:

original:  1100 0000 0000 0000.1100 0000 0000 0000
normaliz: 1.100 0000 0000 0000 1100 0000 0000 0000

因为我们省略了小数点左侧隐含的“1”,所以将其移出,我们有:

$a1:  100 0000 0000 0000 1100 0000 0000 0000 0

取其中的 23 位。因此,如果我做对了,上面的转换器应该说 49152.75 在 IEEE FP 中存储为:

01000111 01000000 00000000 11000000

符号 = 0

指数 = 10001110 (0x8E)

尾数 = 1000 0000 0000 0001 1000 000

(现在,试着想象一下这真的奏效了我的惊讶!)

【讨论】:

    猜你喜欢
    • 2013-04-16
    • 2020-02-03
    • 1970-01-01
    • 2014-01-30
    • 2011-11-22
    • 1970-01-01
    • 2011-11-17
    • 2013-05-13
    • 1970-01-01
    相关资源
    最近更新 更多