Try   HackMD

解讀計算機編碼

編碼發展過程

符號與值

一補數

  • 改良 - 電路設計簡單
    • 去掉了「符號」的表示位元,也就代表不需要有獨立電路將MSB分開來判斷,因而簡化電路
    • 任何減法運算都可以替換成另一種形式的加法運算 => 不需要專門設計「減法器」,也不需要執行減法那繁瑣的借位運算
  • 運用 : 網路封包完整性檢查 (一補述檢驗,最早應用於網際網路前身的 ARPAnet。到了現代為了向下兼容考量,依然是採用這種檢驗方法 )

二補數

  • 改良 - 不用「循環進位」(end-around carry)
    在一補數中,如果進行運算後有溢位,須在和的基礎上再加上進位,也就是又多了一次電路運算

    ​​​​    二進位       十進位
    ​​​​    11111110     -1
    ​​​​ +  00000010     +2
    ​​​​............    ...
    ​​​​  1 00000000      0   <-- 錯誤答案
    ​​​​           1     +1   <-- 加上進位
    ​​​​............    ...
    ​​​​    00000001      1   <-- 正確數值
    
  • 改良 - 0的表示法唯一
    在一補數裡,

    0 分為
    +0
    (00000000) 和
    0
    (11111111),而二補數就只剩下
    +0
    (00000000) 這個唯一的表示法。

    如此最大的好處,並不是數值表示範圍又多了一個空位 而是「判斷是否為0」的運算成本減半 : 不然原本電路需要進行+0、-0的比較後才能確定一數是否真不為0

    ​​​​if(x != 0x00 && x != 0xff) {...}
    

    改良 : 不用循環進位、0的表示法從2種變成1種 (「判斷是否為0運算」成本減半)

二補數編碼原理

首先將0設定為00000000,則1會變成000000012變成00000010,以此類推

至於-1如何表示 ? 我們知道

(1)+1=0,且我們已經確定01的編碼,所以 x + 00000001 = 00000000,也就是說,x11111111

-2呢? 因為

(2)+1=1,而從剛才推算的-1,我們可以再推算出-211111110-3-4 等等亦是同理。

處理器指令和數值編碼的關係

如上述所說,數值早在一補數時期就已經沒有正負號之分了,但是C語言裡面還是有 有 / 無 號數的型態之分,這除了是轉換成十進位(或字元etc)給人看以外,也是給少數處理器指令看的。

因為有些時候一數值是正、是負會影響到處理器指令的行為,比如 : 把原本儲存在8bit位元的某數,搬移到16bit位元的新位址。這時就得先知道此數值到底是正還是負,而不能亂轉移。

比如 : 1001101怎麼移植? 如果是正數,代表

91,則移植後要變成00000000 1001101
9191
; 如果是負數,代表
51
,則移植後要是 11111111 1001101
5151

可以想見,如果搬移時正負號搞錯,則

91 有可能就變成了
51
,這顯然不符合我們對「搬移」的行為預期。