1.6邏輯運(yùn)算
邏輯運(yùn)算在我們今后的編程中會經(jīng)常使用到的。
本節(jié)必須掌握的知識點(diǎn):
u?掌握邏輯運(yùn)算
計算機(jī)中所有的數(shù)據(jù)都是使用二進(jìn)制保存,但是這些復(fù)雜的電路又是如何做運(yùn)算的呢?
邏輯運(yùn)算是CPU運(yùn)算的本質(zhì),不管是計算機(jī)能處理多么復(fù)雜的事情,它最終還是通過電路的開關(guān)來實(shí)現(xiàn)的。邏輯是指對某個事物的推理,“真”和“假”是兩個對立的邏輯狀態(tài),邏輯運(yùn)算是指用數(shù)學(xué)符號來表示邏輯狀態(tài),以便于用數(shù)學(xué)方法研究邏輯問題。我們通常將電路通電狀態(tài)表示為“真”,用數(shù)字“1”表示,不通電表示為“假”,用數(shù)字“0”表示?!盎颉?、“與”、“非”是三種基本邏輯運(yùn)算,計算機(jī)邏輯運(yùn)算也包含“異或”、“位”。
1、或運(yùn)算
或運(yùn)算:匯編中用“OR”表示,C語言中用“|”來表示,可以理解為“或者”,即只要有一個條件滿足就為“真”,用電路來描述:只要有一條電路通電這條總電路就能通電,原理如圖1-6-1:

這是一個并聯(lián)電路圖,不管是A為閉合狀態(tài)、還是B為閉合狀態(tài),還是AB都處于閉合狀態(tài),電燈泡都能亮。我們把電路圖用符號0和1來表示,或運(yùn)算表示只要有一個為1,結(jié)果就為1。我們來看一個寬度為8的或運(yùn)算:

與運(yùn)算:匯編中用“and”表示,C語言中用“&”來表示,它表示兩個條件都成立才能為真,即兩個都為1結(jié)果為1,其他為0,電路實(shí)現(xiàn)原理如圖1-6-2:

這是一個串聯(lián)電路圖,A和B都為閉合狀態(tài),燈泡才能亮。如果有一個開關(guān)沒有閉合,燈泡是不能亮的。即兩個都為1,結(jié)果為1,只要有一個為0 ,結(jié)果為0。
我們來看一下下面的運(yùn)算:

3、異或
異或:匯編用“xor”表示,C語言中用“^”表示,這個不是太好理解,但是它很有用。它表示兩個值不同為真,相同為假。即兩個值如果都為0或者1,結(jié)果為0。一個為0,而另一個為1,結(jié)果為1。如圖1-6-3所示;

這條電路A和B必須是相反的兩種狀態(tài)燈泡才能亮,如果AB都斷開,燈泡無疑是不亮的,如果AB都連上,正負(fù)極抵消,燈泡同樣不能亮。我們來看一下下面的運(yùn)算:

4、非運(yùn)算
非運(yùn)算:匯編中用“NOT”表示,C語言中用“!”表示,它是對某個值求反的運(yùn)算。如 !0 = 1;!1 = 0;非真即為假,非假即為真。
我們來看一下下面的運(yùn)算:

5、左移運(yùn)算
左移運(yùn)算:在右邊添0,數(shù)據(jù)往左移動,用符號“<<”表示,如“0010 << 1 ”表示將0010左移1位,結(jié)果為0100。
6、右移運(yùn)算
右移運(yùn)算:在左邊添0,數(shù)據(jù)往右移動,用符號“>>”表示,如“0010 >> 1”表示將0010右移1位,結(jié)果為0001。
例1:計算機(jī)通過邏輯運(yùn)算實(shí)現(xiàn)四則運(yùn)算。
計算機(jī)的本質(zhì)是邏輯運(yùn)算,不管多么復(fù)雜的運(yùn)算最終都回歸到邏輯運(yùn)算??墒俏覀兩町?dāng)中的計算并不是邏輯運(yùn)算,這又是怎么回事呢?那么CPU是如何通過邏輯運(yùn)算做“+、-、*、/”的呢?雖然我們平常生活中并不會碰到這個問題,但是可以做一些簡單的了解,能幫助我們更清楚地認(rèn)識計算機(jī)的本質(zhì)。
我們來看一下CPU是如何算出2+3等于5的。
計算機(jī)如果要做運(yùn)算,必須要把2和3分別存儲下來,就是先用幾條線路來表示它們。前面我們學(xué)數(shù)據(jù)寬度時講到容器,那我們就用最少的容器來保存2和3。假設(shè)有BYTE x保存2,BYTE y 保存3,那這兩個容器里的數(shù)值是這樣的:

這個結(jié)果放在哪呢?我們再拿一個容器R來保存,假設(shè)它的寬度也是8位,此時R的值為:0000 0001。
第二步,CPU再讓它們進(jìn)行與運(yùn)算:

這一步是為了測試上一步有沒有結(jié)束。
再將這個結(jié)果左移1位,如果這個值等于0,那R就是計算的結(jié)果,不為0重復(fù)之前的操作。0000 0010左移1位等于0000 0100,不為0,所以繼續(xù)運(yùn)算, 將R容器里的值放到x容器中,把與(and)的值放在y里,
???x: 0000 0001
???y: 0000 0100
繼續(xù)之前的操作,先將它們異或,值為0000 0101,將這個值存到R容器。再將x容器和y容器里的與運(yùn)算,值為0000 0000。將它左移一位還是0,所以R的值就是我們計算的結(jié)果,即為0000 0101,轉(zhuǎn)換為十進(jìn)制就是5。
2+3對于我們來說,幼兒園就會算了,而計算機(jī)卻要執(zhí)行如此多步驟。其實(shí)計算機(jī)很笨,它只會按照一定規(guī)則去操作,但是它卻靠著比我們?nèi)祟惪鞜o數(shù)倍的速度幫我們?nèi)祟惤鉀Q很多棘手的問題。
比如我們的寄存器每一位代表不同的含義,假如需要判斷某一位的值,或者更改某一位的值、而其他的值保持不變,那怎么才能做到呢?如有個數(shù)值,我想知道它的第3位是否為1,應(yīng)該怎么運(yùn)算呢?根據(jù)前面的邏輯運(yùn)算,我們知道與運(yùn)算的法則是“有0為0,兩個都為1才為1”,所以我們可以設(shè)置一個第3位為1的值,無論我們要測試的值是幾位數(shù),我們只需要將它與0100進(jìn)行與運(yùn)算即可。當(dāng)這個值與“0100”進(jìn)行與運(yùn)算,只能是兩個結(jié)果,一個結(jié)果為0,一個結(jié)果為 0100,也就是結(jié)果只有兩種情況:“0”和“非0”,若為0,這個數(shù)值的第3位為0,反之,不為零。
所以我們可以利用與、或的特點(diǎn),我們來驗(yàn)證一下,假設(shè)有個要測試的值為8F,我們要測試它的第5位是否為0。
根據(jù)之前的方法,我們將它和“0001 0000”相與:

異或在加密算法里經(jīng)常遇到,兩次異或同一個值,就會還原成異或原來的值。這個需要異或的值我們叫做密鑰。采用異或加密的時候,密鑰的作用很關(guān)鍵。諜戰(zhàn)片里的那些電報也是加密的,常常因?yàn)橐槐久艽a本劇情起伏不斷,可見密鑰的重要性。
比如我們要加密0x2015,密鑰為:0x54計算如下:
加密:每兩位十六進(jìn)制數(shù)分別與54進(jìn)行異或:

u下一節(jié)進(jìn)入?yún)R編章節(jié)。
1、八進(jìn)制數(shù)2-5在計算器中的結(jié)果是:1777777777777777775,為什么?2、使用異或?qū)?7AD6進(jìn)行加密后再解密,加解密密匙:5?3、只用邏輯運(yùn)算計算2-3=?(涉及內(nèi)容:邏輯運(yùn)算、移位、數(shù)據(jù)寬度)