天天看點

《計算機系統:核心概念及軟硬體實作(原書第4版)》——3.2補碼二進制表示

本節書摘來自華章計算機《計算機系統:核心概念及軟硬體實作(原書第4版)》一書中的第3章,第3.2節,作者:[美] j. 斯坦利·沃法德(j. stanley warford)著, 更多章節内容可以通路雲栖社群“華章計算機”公衆号檢視。

無符号二進制表示法僅适用于非負整數。如果計算機要處理負整數,那麼它必須要用一種不同的表示法。

《計算機系統:核心概念及軟硬體實作(原書第4版)》——3.2補碼二進制表示

假設有一個6位的單元要存儲-5(dec)。因為5(dec)是101(bin),是以你可能想到圖3-7所示的樣子。但這是不可能的,因為所有的位必須是0或1。謹記計算機是二進制的。上面這種存儲值要求每個方框可以存儲0或1或破折号,這樣的計算機必須是三進制而不是二進制。

《計算機系統:核心概念及軟硬體實作(原書第4版)》——3.2補碼二進制表示

解決這個問題的辦法是保留單元的第一個方框來表示符号。這樣,6位單元将分為兩個部分—1位符号位和5位數值位,如圖3-8所示。因為符号位必須是0或1,是以一種可能是讓符号位0表示正數,符号位1表示負數。那麼+5可以表示為:

00 0101

-5可以用表示為:

10 0101

在這種表示法中,+5和-5的數值位是相同的,僅僅是符号位不同。

然而,很少有計算機用前面這種代碼,因為如果進行十進制的+5加-5,得到0,但如果進行二進制的00 0101加10 0101(符号位和所有),得到

《計算機系統:核心概念及軟硬體實作(原書第4版)》——3.2補碼二進制表示

這顯然不等于0。如果cpu硬體可以用無符号二進制加法的普通算法對包含符号位的完整數字+5和-5進行相加并得到0,這會更加友善。

補碼(two抯 complement)二進制表示有這個特性,正數由符号位0和與無符号二進制表示一樣的數值位組成。例如,十進制+5(dec)仍然表示為00 0101。

但是-5(dec)的表示不是10 0101,而是11 1011,因為+5加-5是

《計算機系統:核心概念及軟硬體實作(原書第4版)》——3.2補碼二進制表示

注意6位的和都是0,和我們期望的一樣。

按照6位單元的二進制加法法則,11 1011稱為00 0101的加法逆元(additive reverse)。求加法逆元的運算稱為求補(negation),縮寫為neg。對一個數求補也稱為取它的補碼。

現在我們所需的是求一個數補碼的法則。有個簡單的法則是基于反碼(ones抍omplement),反碼是把所有的1變為0,0變為1的二進制序列。反碼也稱為not運算。

例3.8 假設一個6位單元,00 0101的反碼是

not 00 0101=11 1010 □

找出補碼規則的線索是把一個數和它的二進制反碼相加的結果。因為1加0等于1,0加1等于1,是以任意數和它的反碼相加将生成一個全1的序列,然而把一個單獨的1和全1的數相加就會得到一個全0的數。

例3.900 0101加上它的反碼

《計算機系統:核心概念及軟硬體實作(原書第4版)》——3.2補碼二進制表示

這個數是全0的。 □

換句話說,把一個數加上它的反碼,再加1就得到全0的數,是以一個數的反碼加1一定是它的補碼。

例3.10将00 0101的反碼加1得到它的補碼。

《計算機系統:核心概念及軟硬體實作(原書第4版)》——3.2補碼二進制表示

00 0101的補碼是11 1011,即,

neg 00 0101 = 11 1011

11 1011的确是00 0101的負數,因為如前所示兩者相加為0。 □

不管一個數有多少位,對一個數求補的一般法則是:

一個數的補碼等于它的反碼加1。

或者用neg和not運算表示為

neg x=1 + not x

在我們熟悉的十進制中,如果對一個負數值取負,那麼将得到一個正值,代數表達式為

-(-x)=x

這裡x為正值。如果求補碼的法則是有效的,那麼一個負數值的補碼應該是相應的正值。

例3.11如果對-5(dec)取補碼會怎樣?

《計算機系統:核心概念及軟硬體實作(原書第4版)》——3.2補碼二進制表示

瞧!如你所期望的,又得到了+5(dec)。 □

3.2.1補碼的表數範圍

假定有一個4位單元以補碼形式存儲整數,那麼這個單元能表示的整數範圍是多少?

數值最大的正整數是0111(bin),即+7(dec)。這和在無符号二進制數中最大值為1111不同,因為第一位被保留作為符号位且一定是0。在無符号二進制中,用4位單元可以存儲的最大數是+15(dec),所有4位都用于存儲數值。在補碼表示中,能存儲的最大數隻是+7(dec),因為僅有3位用于數值。

《計算機系統:核心概念及軟硬體實作(原書第4版)》——3.2補碼二進制表示

數值最大的負整數是什麼呢?這個問題的答案可能不太顯而易見。圖3-9展示了最大到7的每個正整數的補碼,在圖中看到了什麼規律沒有?

我們注意到補碼運算自動在負整數的符号位生成了一個1,它本來就應該這樣。偶數仍然以0結尾,奇數仍然以1結尾。

《計算機系統:核心概念及軟硬體實作(原書第4版)》——3.2補碼二進制表示

而且,如你所期望的,二進制-6加1得到-5,類似地,二進制-7加1得到-6。我們可以從4位擠出一個更大的負整數-8。二進制-8加1得到-7,是以-8應該用1000表示。圖3-10是一個4位存儲單元的完整有符号整數表。

-8(dec)有一個其他負整數沒有的屬性,如果取-7的補碼會得到+7,如下所示:

《計算機系統:核心概念及軟硬體實作(原書第4版)》——3.2補碼二進制表示

但如果取-8的補碼,得到的還是-8:

《計算機系統:核心概念及軟硬體實作(原書第4版)》——3.2補碼二進制表示

因為4位無法表示+8。

我們已經确定了4位單元的補碼二進制表數範圍以二進制表達是1000到0111,或者以十進制表達是-8到+7。

不管單元包含多少位,模式都是一樣的。最大的正整數是一個0後面全是1,而數值最大的負整數是一個1後面全是0,它的數值比最大正整數大1。-1(dec)用全1表示。

例3.126位補碼表示的表數範圍,用二進制表示是

10 0000到01 1111

或者十進制表示是

-32到31

和其他的負整數不同,10 0000的補碼就是它自己10 0000。還可以看到-1(dec)= 11 1111(bin)。 □

3.2.2基數轉換

把一個負數從十進制轉換為二進制分為兩步。首先,把它的數值部分當作無符号表示轉換為二進制;其次,按照補碼的方式對它取反。

例3.13對于10位單元的-7(dec)

《計算機系統:核心概念及軟硬體實作(原書第4版)》——3.2補碼二進制表示

是以-7(dec)的補碼是11 1111 1001(bin)。 □

在采用補碼表示的計算機中,把一個數從二進制轉換成十進制,總是首先檢測符号位。如果是0,這個數是正數,可以按照無符号數表示進行轉換;如果是1,這個數是負數,可選的方法有兩種。一種是通過取反得到正數,然後再按照無符号數的法則,把它轉換成十進制。

例3.14一個10位單元的内容為11 1101 1010,它代表的十進制數是什麼?符号位是1,是以這個數是負數,首先對這個數取反:

《計算機系統:核心概念及軟硬體實作(原書第4版)》——3.2補碼二進制表示

是以原始的二進制數一定是38的負值,即

11 1101 1010(bin)=-38(dec) □

另一種方法是不用取補碼,直接轉換,即隻用在原始二進制數中為0的那些位的位置值相加,再加1。這個方法是正确的,因為取正整數補碼的第一步就是按位取反。那些本來對正整數數值有貢獻的1變為了0,是以是0而不是1對負整數的數值有貢獻。

《計算機系統:核心概念及軟硬體實作(原書第4版)》——3.2補碼二進制表示

例3.15圖3-11顯示的是11 1101 1010(bin)的為0的位置 ,把這些位的位置值之和加1得到

1101 1010(bin)=-(1 + 32 + 4 + 1)=-38(dec)

這和前面方法得到的結果是一樣的。    □

3.2.3 數軸

看待二進制表示的另一種方法是使用數軸。圖3-12展示了3位單元的無符号二進制表示的數軸,能夠表示8個數字。

《計算機系統:核心概念及軟硬體實作(原書第4版)》——3.2補碼二進制表示

可以通過在數軸上往右移動進行加法運算。例如,4加3,從4開始往右移動3個位置得到7。如果嘗試在數軸上6加3,将超出最右端。如果用二進制進行這個加法,将得到不正确的結果,因為結果超出了範圍:

《計算機系統:核心概念及軟硬體實作(原書第4版)》——3.2補碼二進制表示

把無符号數軸在3和4之間斷開,把右半部分移到左邊,這樣可以得到補碼的數軸。圖3-13顯示了二進制數111現在和000相鄰,之前是+7(dec),現在是-1(dec)。

《計算機系統:核心概念及軟硬體實作(原書第4版)》——3.2補碼二進制表示

即使有經過0,加法仍然是通過在數軸上向右移動來進行的。-2加3,從-2開始向右移動3個位置得到1。如果用二進制計算,答案在範圍内,是以是正确的:

《計算機系統:核心概念及軟硬體實作(原書第4版)》——3.2補碼二進制表示

這些位和無符号二進制6加3是一樣的。我們注意到結果雖然在表數範圍内,但是進位位是1。在補碼表示中,進位位不再表示加法的結果是否是在範圍内。

有時候,隻考慮移動後的十進制數軸,可以完全避免二進制表示。圖3-14展示了補碼數軸,用等值的無符号十進制數代替二進制數。這個例子中,每個存儲位置有3位,是以最多有23或8個數。

《計算機系統:核心概念及軟硬體實作(原書第4版)》——3.2補碼二進制表示

現在,從0到3的無符号數與有符号數是一樣的。此外,通過減8可以從無符号數得到有符号負數:

7-8=-1

6-8=-2

5-8=-3

4-8=-4

例3.16假定有一個8位單元,有28或256個可能的整數值,非負數從0到127。假設采用補碼表示,97加45等于多少?以無符号二進制數計算,和等于

97 + 45=142(dec,unsigned)

但用在補碼表示中,這個和為

142 - 256=-114(dec,signed)

注意,這樣的結果完全避免了二進制表示。為了驗證結果,首先把97和45轉換為二進制并相加:

《計算機系統:核心概念及軟硬體實作(原書第4版)》——3.2補碼二進制表示

符号位是1,是以這是一個負數。現在,确定它的數值大小

neg 1000 1110=0111 0010 (bin)

得出預期的結果。

3.2.4溢出位

在isa3層上二進制存儲的一個重要特性就是每個值都沒有與之相關的類型。在前面的例子中,和1000 1110,作為無符号數解釋時,它是142(dec),但作為補碼表示解釋時,它就是-114(dec)。盡管位模式的值取決于它的類型,是無符号還是補碼,但是硬體對兩種類型不加以區分,隻存儲位模式。

當cpu對兩個存儲單元的内容相加時,它不管它們的類型,隻采用位序列上的二進制加法法則。對于無符号二進制,如果和超出表數範圍,硬體隻是簡單存儲(不正确的)結果,相應地設定c位并繼續往下走。由軟體來檢測相加後的c位,看是否在最高位的那一列有進位發生,并按需采取适當的動作。

我們前面說過,在補碼二進制表示中,進位位不再表示一個和是否在表數範圍内。當運算結果超出表數範圍時,我們稱為出現了溢出情況(overflow condition)。為了為有符号數标示這種情況,cpu中有另一個用v表示的特殊位,叫作溢出位(overflow bit)。當cpu對兩個二進制整數相加時,如果和超出補碼表示的範圍,那麼v設定為1,否則v設定為0。

不論以何種方式解讀位模式,cpu總是執行同樣的加法運算。與c位一樣,如果發生了補碼溢出,cpu不會停下來,它将v位設定為1,并繼續它的下一步工作。由軟體來檢測加法後的v位。

例3.17這裡有幾個6位單元的例子,展示了進位位和v位的情況:

《計算機系統:核心概念及軟硬體實作(原書第4版)》——3.2補碼二進制表示

注意v和c的值有可能是所有的組合。 □

怎樣才能知道發生了溢出情況呢?一種方法是把兩個數轉換到十進制,兩者相加看它們的和是否超出了以十進制表示的範圍。如果是,那就是發生了溢出。

硬體通過将符号位的進位與c位比較來檢測是否溢出發生:如果兩者不同,溢出發生,v為1;如果兩者相同,v為0。

不将符号位的進位與c位比較,也可以通過檢視加數與和的符号,直接确定是否發生了溢出。如果兩個正數相加得到負數或者兩個負數相加得到正數,那麼就發生了溢出;一個正數和一個負數相加是不可能發生溢出的。

3.2.5負數和零位

除了檢測無符号整數溢出情況的c位和檢測有符号整數溢出情況的v位外,cpu還維護了另外兩位,供軟體在運算後進行檢測。它們是n位和z位:n位用于檢測負數結果,z位用于檢測零結果。總的來說,這4個狀态位的函數是

n=1,如果結果是負數。

n=0,其他情況。

z=1,如果結果全是零。

z=0,其他情況。

v=1,如果有符号整數溢出發生。

v=0,其他情況。

c=1,如果無符号整數溢出發生。

c=0,其他情況。

由于n位是符号位的一個副本,是以硬體很容易确定它。而要确定z位,硬體則要費點兒工夫,因為它必須确定結果的每個位是否都為0。第10章展示了硬體怎樣根據結果計算狀态位。

例3.18這裡有三個加法例子,展示了結果的4個狀态位情況。

《計算機系統:核心概念及軟硬體實作(原書第4版)》——3.2補碼二進制表示