作者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)
推 allen0326200:助教用心推! 10/24 22:45
推 allen0326200:sorry沒看原po的ID 以為是TA 謝囉 10/24 22:48
推 ga800360:推! 10/25 01:39
推 maill6802:推 10/25 11:28
推 OppOops:推!! 10/25 18:39
推 han960691:push! 10/25 23:25