作者bill8124 (沅)
标题[分享] 计结:二的补数、Offset 与 Extender
时间Wed Oct 24 22:28:33 2012
二的补数、Offset 与 Extender by bill8124
Outline:
复习一下二的补数
解释 $gp Offset
解释 Extender 的差别
----
◎ 二的补数
范例:
124 =
0000 0001 0010 0100
先取一的补数 -> 1111 1110 1101 1
011 (0变1、1变0)
加 1 变成二的补数 -> 1111 1110 1101 1
100
这个数字以 signed integer 解读就是 -124。
反过来看,如果我们对 -124 做二的补数,
-124 = 1111 1110 1101 1100
-> 0000 0001 0010 0011
->
0000 0001 0010 0100
刚好就会得到原本的 124。
----
◎ 解释 $gp Offset
这个段落其实可以用一句话说完:
「写成 unsigned,读作 signed。」
当 $gp = 1000 8000 ,而我们想要存取的位置是 1000 0000
那我们需要的 offset 就是 -8000
一般而言,人类看到负数不知道如何用 bit 表示
所以要知道 -8000 怎麽用 bit 表示,就要从 +8000 转成 -8000
8000 = 1000 0000 0000 0000
-> 0111 1111 1111 1111
-> 1000 0000 0000 0000
转成 -8000 跟原本一样,这是怎麽回事呢?
计程的时候曾经教到,signed int 的表示范围是
2147483647 = 7FFFFFFF = 0111 1111 1111 1111 1111 1111 1111 1111 (32 bits)
到 -2147483648 = -80000000 = 1000 0000 0000 0000 0000 0000 0000 0000
7FFFFFFF + 1 =
1000 0000 0000 0000 0000 0000 0000 0000 0000
如果用 signed integer 的角度来看,这个数就是 -80000000
(对 signed 来说,看到第一个 bit 是 1 就是负数)
从 unsigned integer 的角度来看,这个数就是 +80000000
(对 unsigned 来说,这个 1 是数字的一部份)
所以 lw $a0, 8000($gp) 其实应该写成 lw $a0, -8000($gp)
因为,这里的 Offset: 8000 应该要看成是 signed integer 的 -8000
另外一个例子。$gp 不变,资料放在 1000 0020
需要 Offset = -7FE0
(1000 8000 - 7FE0 = 1000 0020)
7FE0 = 0111 1111 1110 0000
-> 1000 0000 0001 1111
-> 1000 0000 0010 0000 = -7FE0 (signed) = 8020 (unsigned)
这样就了解为什麽要写成 sw $s0, 8020($gp) 了吧!
我不知道为什麽要故意把 signed 的数表示成 unsigned 的样子,
但总而言之,看到 >= 8000 的 16 bit 数字,就是负数了!
----
◎ 解释 Extender
Extender 有两种: Zero extender 和 Sign extender
Zero extender 就是不管拿到什麽数字,前面都补零
Sign extender 是让 16 bit 数字变成 32 bit,但
数值不变。
举例来说 70C0 = 0111 0000 1100 0000
zero_ext -> 0000 0000 0000 0000 0111 0000 1100 0000 = 7412
sign_ext ->
0000 0000 0000 0000 0111 0000 1100 0000 = 7412
-3A00 = 1100 0110 0000 0000 (这里请自己算出来XD)
zero_ext -> 0000 0000 0000 0000 1100 0110 0000 0000
= C600
sign_ext ->
1111 1111 1111 1111 1100 0110 0000 0000 = -3A00
对 -3A00 的 sign_ext 取二的补数会得到 3A00,各位可以自己试试看。
简单的记法是:
把第 1 个 bit 重复往前填满。(参考上面范例)
顺道一提,通常做 Zero_ext 的时候,原本的数字都会以 unsigned 的形式来用。
以上面的例子来说,这个数字应该看作 C600 而非 -3A00。
CPU 中的 Extender 有个 ExtOp 的 flag
0 代表 Zero_ext,1 是 Sign_ext(从 instuction 的 flag table 可以看出来)
----
希望这篇文有让不太懂这一部份的人,可以完全了解。
另外 ExtOp 的部分,今天计结老师应该是漏讲了。
--
※ 发信站: 批踢踢实业坊(ptt.cc)
◆ From: 114.45.207.217
※ 编辑: bill8124 来自: 114.45.207.217 (10/24 22:29)
※ 编辑: bill8124 来自: 114.45.207.217 (10/24 22:31)
※ 编辑: bill8124 来自: 114.45.207.217 (10/24 22:31)
1F:推 allen0326200:助教用心推! 10/24 22:45
2F:推 allen0326200:sorry没看原po的ID 以为是TA 谢罗 10/24 22:48
3F:推 ga800360:推! 10/25 01:39
4F:推 maill6802:推 10/25 11:28
5F:推 OppOops:推!! 10/25 18:39
6F:推 han960691:push! 10/25 23:25