這幾天想要開始學習系統的原理,本身硬件的系統已經下潛到底層與硬件的各個組成部分進行交互,例如:對CPU的資源管理;內存的管理等。
既然要研究底層,無非從最基礎開始,二進制絕對是計算機的靈魂。二進制使用邏輯運算實現各種數的算數運算是學習二進制的基礎,下面就來分析一下二進制的加減法的實現方式。
加法
回想一下,我們學習十進制加法的時候是先從1位數開始,這里我們也從1位數開始學習二進制的加法。
下面用真值表來表示1位二進制的加法。
X | Y | X+Y | 進位 |
---|---|---|---|
0 | 0 | 0 | 0 |
0 | 1 | 1 | 0 |
1 | 0 | 1 | 0 |
1 | 1 | 0 | 1 |
從表中我們可以看到實現1位二進制加法的基本元素有四個:加數X、加數Y、和X+Y(這里的和只有本位)、進位。
如果從函數的角度來看就是有兩個輸入,兩個輸出。
下面我們來分析一下從輸入到輸出的運算,注意二進制都是用邏輯進行運算,基本的邏輯運算有與、或、非三種。
- 從輸入到和的運算是異或(數同為假,數異為真)。
- 從輸入到進位的運算是與。
上面的1位加法屬於半加器,因為我們沒有考慮來自前面運算的進位,但實際上加上前面的進位運算也很簡單,實際上就是用兩個半加器結合來,各位可以自己去思考一下。
實現了一位全加器之后,就可以實現多位全加器了。
減法
減法可以轉換成加一個負值,比如12 - 8,轉換成12 + (-8),這兩個是等價的。這就引出另一個問題,計算機怎么表示負數的?
按正常思路,可以用最高位代表符號,0代表正,1代表負,比如一個8位二進制:0000 0001是1,1000 0001是-1;這看起來很自然。但是你馬上會發現:0000 0000和1000 0000這兩個值出現矛盾了,從字面上理解這兩個都是0,應該是相等的。但從內存上看這兩個字節又是不相等的。
計算機先驅們用另一種方式存儲負數,首先對於一個整型,我們要先明確它是有符號的還是無符號的,同樣的存儲,有符號和無符號代表的數值可能是不一樣的,以一個8位數為例:
二進制 00000000 00000001 00000010...01111111 10000000 10000001...11111110 11111111
無符號 0 1 2........127 128 129........254 255
有符號 0 1 2........127 -128 -127.........-2 -1
有符號數到達127之后,再往后是-128,后面是-127,-126...一直到-1,這樣8位有符號數的范圍就是:-128~127。
雖然從二進制看一直在漲,但到10000000以后,其表示的含義卻是從負數的最大值往下減。10000000,10000001這些二進制被稱為負數的補碼形式,所以計算機是用負數的補碼來表示負數的。
負數的補碼和對應的正數有一個奇妙的運算關系:
- 對一個正數取反,再加1,會得到其負數的補碼。
- 對一個負數的補碼取反,再加1,會得到其正數。
在計算機中,正數以正常方式存儲,而負數是用補碼的形式來存儲的。
> 計算機內存| 00000111 | 11111001|
| 7 | -7 |
如上所示,用補碼存負數有一個好處,就是可以用加法代替減法。如下所示
5-3
=5+(-3)
=(00000101)+(11111101)
=(00000010) 正數
=2
4-6
=4+(-6)
=(00000100)+(11111001)
=(11111101) 補碼代表負數
=-2