最近學習計算機組成原理時,結合視頻和我的理解作的一些筆記。可能文中有錯誤或者描述不恰當的地方,歡迎評論區指出。git
108D
爲例,它對應的二進制數是 1101100
,這實際上也就是它的無符號數,能夠看到全部的位都是數值位。00000000
到 11111111
,也就是 0 到 255定義:有符號數就是有體現正負號的數,整個機器字長的所有二進制位中,最高位做爲符號位,0 表示正數,1 表示負數,其他位則是數值位。依然以108D
爲例,它對應的二進制數是 1101100
,而對應的有符號數則要在最前面加上符號位 0,即它的有符號數是 01101100
.github
表示範圍:以八位二進制數爲準,範圍應該是從負數到正數,即從 11111111
到 01111111
,也就是 -127 到 127ide
+108D
就是真值01101100
就是機器數。-156D
(真值)= 110011100B
(機器數)學習
簡單點理解,原碼就是符號位加上真值(二進制)的絕對值,同時用逗號將符號位和數值位隔開。好比,+1 就是 0,0000001
,-1 就是 1,0000001
。3d
原碼的特色是簡單、直觀,可是原碼在進行加法運算的時候會出現問題。正數加正數或者負數加負數是正常的,可是正數加負數就會出錯。好比咱們如今想要計算 -1+3,咱們心想:-1 是 10000001
,+3 是 00000011
,加起來獲得的是 10000100
,因此結果是 -4,但 -1+3 應該是等於 2,因此這個結果是錯的。咱們發現,原本應該作的是加法運算,但實際上變成了減法運算(-1-3=-4)。code
咱們首先想到,能夠經過將「正數加負數」轉化爲「正數減正數」來手動糾正這個錯誤。上面的例子就變成 00000011
減 00000001
,結果是 00000010
,也就是 2,這個結果是正確的。視頻
可是每次都這樣手動轉化,計算起來仍是太麻煩了。因而咱們接着想:有沒有一種方法,可讓「正數加負數」中的負數等價於一個正數,從而確保始終進行的是相加操做呢?blog
因而這時候就引出了補碼的概念。get
補數和模:理解補碼以前,咱們先來理解兩個概念:補數和模。 拿時鐘舉例,想要從10點撥到8點,有兩種作法,一種是逆時針撥2個單位,記做-2;一種是順時針撥10個單位,記做+10,這兩種操做是等效的(有點負數等價於一個正數的意思)。這時候咱們就說,-2 是 +10 以 12 爲模的補數,記做-2≡+10(mod 12)
,同理,-5 至關於 +7,-4 至關於 +8。it
那麼怎麼基於補數和模的概念將「正數加負數」轉化爲「正數加正數」 —— 即怎麼令負數等價於一個正數呢?假設咱們如今有一個寄存器能夠存放四位二進制數(此時,模爲16),咱們想要讓 1011
變成 0000
,最容易想到的辦法就是 1011-1011=0000
,注意這裏是正數加負數。想要變成正數加正數,就要找到等價於 -1011
的正數,-1011
就是 -11,-11 以 16 爲模的補數就是 +5,+5 就是 +0101
,這個正是咱們要找的那個等價正數,所以這時候,1011-1011
變成了 1011+0101
,其結果是 10000
,不要忘了寄存器只能存放四位,因此結果實際上是 0000
,剛好與咱們「正數加負數」時獲得的結果無異。
接着引入補碼的概念:
仍是上面的例子,1011-1011
,也就是11-11,咱們考慮+11和-11,+11的原碼=補碼=01011
,-11的原碼是11011
,所以補碼是10101
,那麼01011+10101
就會等於100000
,由於寄存器是五位的,把前面的1去掉,那麼結果就是00000
,也就是0,和上面的運算結果一致。
反碼很好理解:
補碼存在的問題是,僅從補碼自己來看,很難比較兩個數的大小,爲此引入了移碼的概念。移碼指的是在真值(二進制)的基礎上加上一個偏移量,一般這個偏移量是2^n。其中,n是數值位的位數。例如,對於-10101
,其移碼是2^7+(-10101)=10000000+(010101)=0,1101011
。 固然,咱們有簡單的方法能夠計算一個數的移碼:無論正數仍是負數,其移碼都等於補碼的符號位取反。
定點數的加減運算實際上就是補碼的加減運算。咱們來看一個例子:
假設機器字長爲 8 位(含1位符號位),A=15,B=-24,如今求 A+B 和 A-B。
A 的補碼是 0,0001111
,B 的補碼是 1,1101000
,那麼 0,0001111+1,1101000=1,1110111
,轉化爲原碼,再轉化爲真值,獲得 -9,這是正確的。同理,A-B 就是 A+(-B),-B 的補碼是 0,0011000
,那麼 0,0001111+0,0011000=0,0100111
,最後轉化爲真值,獲得 +39,這也是正確的。 咱們再來看另外一個例子:
假設機器字長爲 8 位(含1位符號位),A=15,B=-24,C=124,如今求 A+C 和 B-C。
咱們一樣按照上面的流程來進行計算,最後得出:A+C 結果是 -117,B-C 結果是 +108,這兩個都是錯誤的。爲何會出現這樣的狀況呢?
這種狀況就叫溢出。出現的緣由,簡單來講就是:運算結果太大了,或者運算結果過小了。就上面的題而言,8 位二進制數所能表示的數字的範圍是有限的,當正數加正數的時候,結果可能過大,超出了最大值,此時稱爲上溢;當負數加負數的時候,結果可能太小,夠不到最小值,此時稱爲下溢。以下圖所示:
咱們拿 3 位二進制數來理解這個問題。假設 3 位二進制數能夠表示的範圍以下:
如今咱們進行 2+2 操做,那麼就是 010+010
,結果就是 100
,這已經超出了正數能夠表示的最大範圍,也就是發生了上溢。因此此時獲得的是 -4,這是一個錯誤的結果。
前面說過,溢出的緣由要麼是運算結果太大,要麼是運算結果過小,其實從這句話咱們能夠看出,正數和負數相加是不會發生溢出的,由於其結果必然在能夠表示的範圍內,惟一可能會發生溢出的狀況,要麼是正數加正數,要麼是負數加負數。那麼,如何判斷在這兩種狀況下是否會發生溢出呢?有三個方法:
咱們仍是拿上面的第二個例子解釋:
能夠看到,A+C 中,兩個操做數符號位都是 0,也就是都是正數,但結果數的符號位倒是 1 ,也就是負數,那麼很明顯它發生了上溢;
同理,B-C 中,兩個操做數符號位都是 1,也就是都是負數,但結果數的符號位倒是 0,也就是正數,那麼很明顯它發生了下溢。
看第一個式子,進行運算的時候,符號位沒有產生進位,可是最高數值位向前產生了進位,這時候判斷它發生了上溢; 看第二個式子,進行運算的時候,最高數值位沒有產生進位,可是符號位向前產生了進位,這時候判斷它發生了下溢。
這種方法是將一位符號位改成兩位符號位表示:正數符號爲 00,負數符號爲 11。那麼前面的例子就會變爲:
這時候,計算機只須要看結果數就能知道是否發生溢出 —— 只要結果數的兩位符號位相異,那麼就必定是發生了溢出。 同理,咱們回過頭看第一個沒有溢出的例子:
能夠發現兩次運算的結果數的兩位符號位都是同樣的,由此判斷這兩次運算都沒有發生溢出。