聲明:本篇文章是根據bilibili上的一個計算機基礎的英文小視頻,jean的一層層抽象的方式來講計算機原理。
機械繼電器,繼電器就是用電控制的機械機關,繼電器里面有根'控制線路',控制電路是開還是關,'控制線路'連接一個線圈,當電流經過線圈,線圈產生磁場,磁場吸引金屬臂,從而閉合電路。可以把繼電器比喻成水龍頭,繼電器控制的是電子。繼電器可以連接到其他電路,比如馬達,馬達讓計數齒輪+1,就完成了計數計算。1940年的時候一個好的繼電器可以1秒鐘內翻轉50次。機械繼電器太慢容易磨損出現故障---就出現了電子管。二級電子管中一個級就是燈絲,它是負責發(fā)射電子的,第二個級通上正電就可以接受電子。三級電子管是有第三個控制級,向控制級施加正電荷,就是允許電子流動,施加負電荷就是阻止電子流動。所以也是通過控制線路來實現斷開或者閉合電路,就和繼電器實現的功能一樣了。但是電子管每秒鐘可以開關數千次。所以三級電子管,也叫三級真空管成了無線電、長途電話等電子設備的基礎,并且持續(xù)了近半個世紀。
三級電子管時代的計算機是計算機從機械時代走向電子時代,此時就出現了可編程的計算機,其編程的方法是把幾百根電線插入插板,有點像老電話交換機,是為了讓計算機執(zhí)行正確操作。雖然'可編程'但還是要配置它。世界上第一個真正的通用可編程計算機每秒可執(zhí)行5000次十位數加減法,但經常工作半小時電子真空管就出現故障,于是晶體三極管出現了。
晶體三極管也有兩個電極,電極之間有一種材料隔開它們,這種材料有時候導電有時候不導電,這就是半導體,控制線連接到一個'門'電極,通過改變'門'的電荷,我們可以控制半導體材料的導電性,來允許或者不允許電流流動。就實現了繼電器一樣的功能。晶體管是固態(tài)的,并且體型可以遠遠小于繼電器和真空管。這就誕生了更小更便宜的計算機。第一個消費者也可以買得起的計算機是有3000個晶體管每秒可以執(zhí)行4500次加法。
如今,計算機里的晶體管小于50納米,而一張紙的厚度是10萬納米。所以晶體管不僅小還超級快,每秒可以切換上百萬次,并且不易磨損能工作幾十年。
而晶體管的主要材料就是半導體硅,硅谷的英特爾就是現在著名的計算機芯片制造商。
計算機從繼電器到真空管到晶體管,我們是讓電路開閉得非常非???。那么電路開閉和計算有什么關系?我們沒有馬達和齒輪呀?答案是布爾邏輯和邏輯門。
在計算機的繼電器時代,我們是用齒輪數來代表數字的,齒輪用10個齒,就是十進制。到了計算機的電子管時代,我們就只是用開/關兩種狀態(tài)代表信息,這叫二進制,就是用兩種狀態(tài)表示,只要true or false即可,電路閉合電流流過代表真,電路斷開無電流就代表假,二進制就將真假寫成10。晶體管雖然可以不只是開關,還可以讓不同大小的電流通過,所以曾經也出現過三進制五進制甚至十進制,但是進制越高就代表狀態(tài)越多,就越難區(qū)分信號。如果手機快沒電了或者附近有電噪音,或者附近有人用微波爐,信號就有可能混在一起,加上每秒百萬次變化的晶體管讓問題變得更糟糕,所以我們需要盡可能地把每種信號分開,此時如果只用開關兩種信號就不存在上述問題了。
此外,數學里面還專門有一門學科就叫布爾代數,這門數學就是專門處理真假問題的,它可以解決很多法則和運算。我們學的數學里面的代數,變量的值是數字,可以進行加減乘除等操作,但在布爾代數種,變量的值是true 和false,能進行邏輯操作。布爾代數中有三個基本操作:NOT, AND 和OR。還有1個高級操作叫異或XOR。
not操作就是把布爾值反轉,把true進行not就變成false,反之亦然。晶體管是控制電流的開關,有3根線:2根電極和1根控制線。當控制線通電時,電流就可以從一個電極流到另一個電極,我們把控制線當作輸入input,底部的輸出電極當作輸出output。所以,1個晶體管,有一個輸入和一個輸出。如果我們打開輸入input on, 輸出也會被打開output on,因為電流可以流過,如果我們關閉輸入input off ,輸出也會關閉output off, 因為電流無法通過。用布爾代數的術語來說就是輸入為真輸出為真,輸入為假輸出為假,我們把這個做成'真值表'。當我們將上面的電路稍作修改就可以實現NOT:我們還把控制線作為input,但在流入電極也就是正電級上再接入一個線,并把這條線作為output, 當input為on時,電流從負電極流出了,output就是off, 當input為off時,電流就從正電級接的那個線output線流出了,此時output線就是on,這樣就實現了input on output off , input off output on。這就是一個最簡單的非門電路。NOT門,之所以叫門是因為它能控制電流的路徑。
AND操作有2個輸入1個輸出。2個輸入都是true,輸出才是true。就是:true+true=true, true+false=false,false+true=false,? false+false=false。and門需要2個晶體管串聯在一起,因為要兩個輸入,兩個晶體管的控制線作為input1和input2,只有input1和input2都通電,output才有電。這樣就實現了與門。
OR操作也是有2個輸入1個輸出。只要2個輸入里有一個是true,輸出就是true。就是:true+true=true, true+false=true, false+true=true, false+false=false。or門需要2個晶體管并聯在一起。其中兩個輸入input1和input2分別是兩個晶體管的控制線,output是電路輸出線,就是負電極線。這樣就實現只要有一個input是true,輸出就是true。就是一個或門電路。
小結:至此三個基本電路:非門,與門、或門我們都知道了。
非門的畫法是一個三角形加一個圓圈。與門是一個大D?;蜷T是一個小魚的樣子。
通過非門與門或門我們就可以搭建更大的組件,比如異或門XOR, 異或門是:true+true=false, true+false=true, false+true=true, false+false=false。XOR門我們可以先放一個or門再加一個and門,并且在and門上再加一個not門,然后把兩個輸出串聯到一個and門上,就變成了XOR門了。XOR門的畫法是一個小魚加個笑臉。
當我們把上面的這些門都包裝起來,我們根本不需要知道每個門都具體用了幾個門?這幾個門又是用幾個晶體管怎么拼接起來的?電子是怎么流過半導體的?芯片設計師在設計處理器時,很少在晶體管的層面上思考,而是在更大的組件比如邏輯門,或者是由邏輯門組成的更大組件的基礎上思考的。而程序員也更是不用考慮邏輯是怎樣在物理層面實現的。
從電信號到表示數據用的true and false, 下面就開始"計算"了。
我們僅僅用上面講的這些邏輯門就可以判斷復雜的語句了,比如:if A and B or C and D, 那么E=true。
前面說的是我們用晶體管做邏輯門,通過邏輯門我們可以判斷布爾語句。
#計算機如何存儲和表示數字?
布爾代數只有兩個值:true 和 false。我們規(guī)定一個二進制值可以代表1個數。我們可以把真和假當作1和0。如果我們想表示更多的數,加位數就好了呀,和十進制一模一樣。二進制的加法和十進制的加法也是一樣,按位置加,滿2進1。
二進制中一個1或者一個0就叫一位bit, 8位為一個字節(jié)tyte,8位可以表示的最小的數是0,最大的數是255。我們經常說8位機,8位圖像,8位音樂,意思就是計算機里面的大部分操作都是8位8位這樣處理的。但是8位只有256個值,也就意味著8位圖像只有256種顏色。如果有10個字節(jié)tyte,就意味著有80位。千字節(jié)kb,兆字節(jié)mb,千兆字節(jié)gb。所以MB是百萬字節(jié),GB是十億字節(jié)。而TB是一萬億字節(jié),也就是8萬億個0和1。
我們經常說的32位或者64位計算機,意思就是一塊塊處理數據,每塊是32位或者是64位,32位能表示的最大數是43億左右,也就是32個1能表示為4,294,967,295。所以現在我們的照片是非常清晰的,因為我們現在都用至少32位顏色,它有上百萬種顏色,所以色彩非常豐富。
正負數的表示:一般情況下大部分的計算機都用第一位表示正負,1表示負,0表示正,用剩下的31位表示數字。能表示的數字是正負20億左右。但有時這個數字還是不夠用的,比如全球有70億人口,銀行存款有萬萬億,所以此時64位計算機就出場了。
此外,每個數字除了數值大小,正負號,還必須有一個內存地址作為它的標記,這個標記是為了方便存取數據。
計算機如何處理非整數?就是小數點可以在數字間浮動,有好多種方法表示浮點數,最常見的就是IEEE754標準。
計算機如何處理字符?計算機用數字表示字母,最直接的方法就是給字母編號,ASCII編碼。ASCII碼再演變到Unicode。
計算機如何處理圖像、聲音、視頻數據?用格式,比如mp3,GIF, 像ASCII碼用二進制來表示字母一樣,用二進制編碼聲音/顏色,表示照片、電影、音樂。
這些標準歸根到底都是一長串位。短信、視頻、網頁,甚至操作系統(tǒng),都不過是一長串1和0。而這些標準和編碼讓不同公司制作的計算機能夠互相交換數據。
#計算機如何計算和處理數字?
數字的加減乘除由計算機的'算術邏輯單元'處理,arithmetic & logic unit,簡稱ALU。? ? ALU是計算機的數學大腦,是理解現代計算機的基石。ALU就是計算機里負責運算的組件,基本其他所有部件都用到了它。其中最著名的ALU就是intel 74181 , 1970年它發(fā)布時,是第一個封裝在單個芯片內的完整ALU。74181用了大概70個邏輯門,但也只是一個4位ALU, 不能執(zhí)行乘除,但它向小型化買進了一大步,讓計算機更強大更便宜。一個8位的ALU會需要數百個邏輯門。8位的ALU有兩個輸入,A和B,都是8位bits, 形狀用一個大V表示。
現在我們用前面的邏輯門制作一個簡單的ALU電路,功能和74181一樣。再后面我們就用這個ALU從頭做出一臺電腦。
ALU有2個單元,1個算術單元和1個邏輯單元。
算術單元,它負責計算機里所有的數字操作,比如加減法,比如給某個數字+1,這叫增量運算。
如果我們想把兩個數字相加,我們就會用到and, or , not, xor邏輯門。按位加,每個位上有四種情況:1+1, 1+0, 0+1, 0+0,如果用異或門電路1+1=0,1+0=1,0+1=1,0+0=0,符合二進制的加法邏輯,所以我們就把xor用作1位的加法器adder, 但是只要一個異或門是不夠的,因為1+1=10是要進位的,所以我們額外一根線代表進位。只有輸入是1和1時才需輸出是true,也就是進位。所以我們在異或門電路里面再并聯一個and門,這個and門叫'半加器'。當我們把xor門和and門封裝在一起,就是兩個輸入,兩個輸出。只有當兩個輸入是1和1時,就輸出總和0和進位1。
如果我們要處理超過1+1的運算,就要'全加器'。當'半加器'輸出了進位,就意味著我們計算下一列的時候,都得加3個數在一起而非2個數。所以'加全器'有三個輸入,就是8種情況,就是8種輸入。我們先用'半加器'將第一輸入和第二輸入相加,然后再把第三輸入和前兩個輸出一起送到第二個'半加器',再連接一個or門檢查進位是不是true,就成功計算出1+1+1的結果了。這就是'全加器'了。我們把全加器封裝,就會實現三個0或1的輸入,輸出是三個輸入的總和和進位。
如果我們我們想相加2個8位數字A和B呢?先用一個半加器把A0和B0相加輸出sum0, 再并聯一個全加器,輸入全加器的是A0B0的進位和A1B1,輸出sum1,再并聯一個全加器,輸入是A1B1的進位和A2B2,輸出sum2,......如此并且7個全加器,就可以計算2個8位數字的加法了。這個就叫'8位行波進位加法器'。注意如果第9位有進位,就代表這2個8位數字太大,相加超過了8位,這就出現了溢出overflow,也就是計算出現了錯誤,少了一位。如果要避免溢出,我們就需要并聯更多的加全器,比如多到可以操作32位數字、64位數字等,就不容易出現溢出了。但代價是需要更多的門電路,計算次數要增加,計算時間也要增加,但是我們現在計算機的運算都是每秒幾十億次的量級,并且現代計算機用的加法電路和上面我們模擬的電路還有點不同,是把上面的電路給優(yōu)化了,叫'超前進位加法器',它更快,也是把二進制數相加。
ALU的算術單元除了做加法,還可以減法,乘法除法,比如乘法就用多次加法來實現,比如12*5就用4次相加完成。簡單的加法器就是這么做的,比如恒溫器、電視遙控器、微波爐。這樣慢是慢但是可以算出來,而我們現在用的筆記本和手機用的就是更好的處理器,有專門做乘法的算術單元。乘法電路比加法電路復雜的多,有更多的邏輯門。這就是算術單元。
邏輯單元:logic unit, 邏輯單元執(zhí)行邏輯操作,也是把上面學的那些門各種花式排列組合來執(zhí)行邏輯操作,比如執(zhí)行最簡單的數值測試,比如測試一個數字是不是負數,比如檢查ALU輸出是否為0的電路,就是用7個或門組成。通過這個門的數據只有全部為0才輸出為0,否則為1。
除此之外,我們還需要告訴ALU去執(zhí)行什么操作,是執(zhí)行加法還是減法?所以我們還需用4位的操作代碼operation code(4 bits),比如1000表示add, 1100表示subtract, 操作代碼告訴ALU執(zhí)行什么操作。我們現在做的ALU是8位的,就是輸入inputA和inputB都是8位,輸出output也是8位。但是ALU還要輸出一堆標志flag,這些flag是一位的,代表特定狀態(tài)。
比如相減兩個數字,結果為0,我們的零測試電路會將零標志zero flag設為True,也就是1,如果想知道兩個數字是否相等,這樣就可以知道了。如果想知道A是否小于B,可以用ALU來算A-B,看負標志是否為True,如果是true就是A小于B,這就是negtive flag
。此外,我們還有一條線連到加法器的進位,如果有溢出overflow flag,我們就知道要進位,這就是溢出標志。
高級的ALU有更多的標志,但是zero flag, negtive flag, overflow flag是最基本的標志。
至此,我們就知道現代計算機是如何在沒有齒輪和杠桿的情況下進行運算了。
#用ALU做CPU
上面我們用ALU算出來結果如果扔掉就沒什么意義了,我們的找個方式存儲起來。這就要用到計算機內存了。
我們計算中的數據丟失是因為我們的計算結果都放在'隨機存取存儲器'ram, random access memory,這種存儲器只能在有電的情況下存儲東西,比如游戲狀態(tài)。另一種存儲memory叫持久存儲,電源關閉時數據也不會丟失,它是用來存儲結果變量、程序、代碼等數據。
現在我們來做一個只能存儲1位數據的電路,然后再擴大,進而做出我們的內存模塊。然后再和ALU結合起來就做出了cpu!
#寄存器和內存
比如,我們現在有一個或門or電路,inputA,input B,output, 如果我們把output的線路上連一條電線到inputB上,就是or電路的輸出又瞬間送到了inputB了。這個電路,不管我們輸入的inputA是0還是1,它的輸出都是1了,所以不管是input A通電還是不通電,它都永久輸出了一個1,也就是永久存了一個1。
同理,如果我們現在又一個與門and門電路,也是上面的操作,這個電路始終都輸出0。
現在我們就有了一個能存0和1的電路,我們把這兩個電路連接起來就是'and-or latch'也叫'and-or 鎖存器'。這個鎖存器有兩個輸入:set input and reset input,即'設置'輸入和'復位'輸入,設置輸入把輸出變成1,復位輸入把輸出變?yōu)?,如果設置和復位都是0,電路就會輸出最后放入的內容。也就是說它存住了一位的信息。這叫'鎖存',因為它鎖定了一個值。
放入數據的動作叫'寫入', 拿出數據的動作叫'讀取'。
寄存器的輸入有:數據輸入data in, 允許寫入線write enable,
寄存器的輸出有:數據輸出data out
當寫允許線=0表示寫操作關閉,此時數據輸入線不管是輸入0還是1,數據輸出都是0不會改變,所以內容不會變化。
當寫允許線=1,表示可以寫操作,此時數據輸入線輸入1就輸出1。現在如果關閉寫允許線,輸出會保持1,就是此時不管數據輸入線是輸入1還是0,輸出都是1。這樣就把1這個值保持起來了。
這樣就是保持了1位bit的數據。如果我們并排放8個鎖存器,就可以保持8位信息。比如一個8bit數字?,F在的電腦一般都是64位寬的寄存器。我們用一根線連接所有寫允許線,把它設為1,然后用64條數據線發(fā)數據,然后將寫允許線設回0,這樣64位的值就存起來了,用64根線連接到輸出端,就是可以輸入之前存入的數據了。所以64位寬的寄存器要129條線,256位寬要513條線。這樣的電路線路太多,所以比如256位寬的寄存器,我們就將這256個寄存器拍成16*16的矩陣形狀,要啟用某個寄存器,就打開相應的行線和列線,此時我們在行線和列線上再加一個and門,也就是只有行列線都輸入為1時,and門輸出才是1,這個1就傳入寄存器的寫允許線。這樣我們就可以只用一根數據線連接所有鎖存器來傳遞數據了。
我們可以用類似的技巧來做'允許讀取線'來讀取數據,即從一個特定的存鎖器讀取數據。這就是256位的存儲。這樣256位的存儲器就只需要1條數據線,1條'寫允許線',1條'允許讀取線',還有16行16列的線用于選擇鎖存器。16+16+1+1+1=35條線即可。
比如我們存了一個數據的地址是'12行8列',由于我們最多就是16個行列,所以用4位就夠了,12的二進制是1100,8的二進制是1000,所以12行8列就是11001000。我們要將這個地址值轉化為行和列,就要用到'多路復用器',multiplexer, 一個多路復用器處理行,另一個多路復用器處理列。
太復雜了,我們就把它當成一個256位的存儲器吧。這存儲器的第一個輸入是一個8位的地址線,4位代表行4位代表列。第二個輸入是'允許寫入線'。第三個輸入是'允許讀取線'。第四個輸入是數據線,用于讀/寫數據。
然后我們將上面的256位存儲器復制多個并排放到一起,就是寄存器組了。我們把寄存器組也看成一個整體,就是一個可尋址內存。這個內存有256個地址,每個地址能讀或寫一個8位值。
內存的一個重要特性是:可以隨時訪問任何位置,所以叫'隨機存取存儲器',簡稱ram,ram就像人類的短期記憶,記錄當前在做什么。
一條真的內存條,上面焊接了8個內存模塊,其中一個內存模塊放大可以看到有32個內存方塊,放大其中一個方塊可以看到有4個小塊,放大一個小塊可以看到存一個'位'的矩陣,這個矩陣是128位*64位,共8192位,8192*4=32768*32,就是一個芯片大約存100萬位,ram有8個芯片,所以總共有800萬位。
現在我們用鎖存器做一塊SRAM靜態(tài)隨機存取存儲器。還有其他類型的ram,比如dram, 閃存Flash memory和NVRAM,它們在功能上和SRAM相似,但是是用不同的電路存單個位,比如用不同的邏輯門,電容器,電荷捕獲或憶阻器。但根本上,這些技術都是矩陣層層嵌套來存儲大量信息。
#CPU
我們已經做了一個算術邏輯單元ALU,輸入二進制,它回執(zhí)行計算。
我們還做了2種內存:寄存器--很小的一塊內存,能存一個值,之后我們增大存儲容量,做出了RAM。ram是一大塊內存,能在不同地址存大量數字。
現在我們把上面的兩個東西組裝在一起就構成了計算機的心臟了。計算機的心臟就是'中央處理單元',簡稱cpu。
cpu負責執(zhí)行程序,程序由一個個操作組成,操作又叫'指令'instruction, 指令是指示計算機要做什么的。如果是數學指令,比如加減指令,cpu會讓ALU進行數學運算。如果是內存指令,cpu會和內存通信,然后讀/寫值。
cpu組建:首先,要一些內存,上面我們做的ram即可。假設ram只有16個位置,每個位置存8位。
? ? ? ? ? ? ? 其次,再來四個8位寄存器,叫ABCD,寄存器用來臨時存數據和操作數據。
數據是以二進制值存在內存里,程序也是存在內存里。我們給cpu支持的所有指令分配一個ID。比如,我們用前4位存'操作代碼'operation code, 簡稱操作碼opcode, 后4位代表數據來自哪里,可以是寄存器或內存地址。
? ? ? ? ? ? ? 再次,我們還需要2個寄存器,一個用于追蹤程序運行到哪里了,我們叫它'指令地址寄存器', 就是存當前指令的內存地址。另一個寄存器存當前指令,叫'指令寄存器'。這樣我們就完成
當啟動計算機時,所有寄存器從0開始。此處的例子,假如我們在ram里放了一個程序,cpu的第一個階段叫'取指令階段',負責拿到指令,首先將'指令地址寄存器'連接到ram,寄存器的值初始化為0,因此ram返回地址0的值。假如ram地址0上的值為0010 1110,這個值就會復制到'指令寄存器'里,現在指令就拿到了,現在開始要弄清是什么指令才能執(zhí)行execute,而不是殺死kill它,這就是'解碼階段'decode phase. 前4位0010是load A指令。意思就是把ram的值放入寄存器A。后4位1110是ram的地址,轉成十進制是14。
說明我們要首先有一個指令表instruction table, 這個表列出指令是load A , 描述是read ram location into register A,四位操作碼是0010, 地址或寄存器是4-bit ram address....等等指令列表。
接下來由'控制單元'進行解碼,'控制單元'也是由邏輯門構成。為了識別load A指令,我們需要一個電路,檢查操作碼是不是0010?,F在知道了,我們就可以執(zhí)行了,開始'執(zhí)行階段',用'檢查是否load A指令的電路'可以打開ram的'允許讀取線',把地址14傳過去,ram拿到值0000 0011,十進制的3。因為load A指令只是想把這個值放到寄存器A,其他寄存器不受影響,所以需要一根線,把ram連到4個寄存器,用'檢查是否load A指令的電路'啟用寄存器A的'允許寫入線',這樣就成功了。成功把ram地址14的值放到了寄存器A。指令完成,我們就關掉所有線路。去拿下一條指令,我們把'指令地址寄存器'+1, '執(zhí)行階段'就此結束。
。。。。。。
前面我們將的例子的最開始是假設程序已經在內存里了,也就是已經在ram里面了,cpu如何先從ram里面一條條拿到指令(通過指令地址寄存器把數據從ram復制到指令寄存器),然后指令寄存器開始解碼,然后執(zhí)行指令。如此順序執(zhí)行內存的程序。
那么,最開始程序是如何"進入"計算機的,也就是程序是如何加載到內存的?
#早期的編程方式:
用可穿孔紙卡,紙卡的特定位置有沒有孔決定了線是高還是低。一連串的紙卡就形成一連串的連續(xù)指令。穿孔紙卡便宜、可靠、易懂。比如人口普查,一個人生成一個紙卡,這個紙卡比如有種族、性別、年齡、姓名、學歷等信息,每個字段都有幾種選擇,那么一個人如果是男,則在性別的那一行男的那一列打一個孔。這樣人口普查時,只要把普查到的人口的卡紙一張張放入計算機,計算機根據這些孔就計算出有多少男人多少女人,多少漢族多少其他民族。這種編程方式,卡紙傳入計算機的不是指令而是數據。一摞穿孔卡紙輸入,穿孔卡紙攜帶的信息就被加載到內存了,一旦程序和數據加載完畢,電腦就開始執(zhí)行了。
后來演變成一個控制面板,就是把幾百根電線插入插板,有點像以前的電話交換機,目的是讓計算機不同的部分互相傳遞數據和信號。這種編程方式傳入計算機的信號不僅有數據還有簡單的指令,就是這些指令我們還要配置它。就是說允許不同的指令或者說運行不同的程序要重新接線。
再后來演變成一個面板上用一大堆的開關和按鈕,這樣也可以做到切換電路的效果。但是這個面板上有各種指示燈,就代表了各種函數的狀態(tài)和內存中的值,所以它的面板是一個巨大的控制臺。有點像我們現在的游戲機。也有點像科幻片里的宇宙飛船的控制臺。
直到我們的硬件——內存逐漸成熟,我們才把存在面板上的程序轉向存在內存中變得可行。這種程序修改方便,cpu讀取快速。此時我們的電腦才叫作'存儲程序計算機'。后來隨著內存不斷地擴容,內存不僅可以存儲要運行地程序還可以存儲程序運行需要的數據,也包括程序運行時產生的臨時數據。這種程序和數據都存在一個地方叫'馮諾伊曼結構'。馮諾依曼計算機的標志是:一個處理器(有算術邏輯單元)+數據寄存器+指令寄存器+指令地址寄存器+內存(復制存數據和指令)。
比如我們用python編程,我們要算兩個數字相加會這樣寫:
a=3, b=9, c=a+b
這三行pyhon語言會被傳入python編譯器,編譯成匯編語言:
load a 14
load b 15
add b a
store a 13
HALT
意思就是我們在寫pyhon語言的時候已經忽略了計算機底層的運行邏輯。我們不需要去管寄存器或內存的位置,編譯器都幫我們搞定了。作為程序員我們只需要創(chuàng)建代表內存地址的'變量',給變量取名字即可,我們就可以把兩個數存在變量里面了。然后把兩個數相加把相加的結果存在變量c里面。計算機底層操作時,編譯器可能把變量a存在寄存器a,但我們是不需要知道這些的。匯編語言再被操作系統(tǒng)的編譯器把匯編代碼轉化為機器碼。所以我們現在的編程語言編程是不需要再接觸cpu特有的匯編碼和機器碼,使得編程難度大大降低。
#編程語言都具備的元素:
規(guī)定句子結構的一系列規(guī)則叫語法。
比如'語句':a = 5就表示創(chuàng)建一個叫a的變量,把數字5放在這個變量里面。這就是'賦值語句',就是把一個值賦給一個變量。
程序由一個個指令組成,從第一條語句開始,一句一句運行到結尾。
例子,假如我們寫一款游戲,拍蟲子,關卡越高,蟲子越多,游戲者要在蟲子損壞繼電器之前把蟲子全部抓住。游戲者有幾個備用繼電器。開始編寫時,我們需要一些值來保存游戲數據,比如當前關卡數、分數、剩余蟲子數,游戲者還剩幾個備用繼電器。所以我們要初始化變量,初始化就是設置最開始的值:關卡=1, 分數=0, 蟲子數=5, 備用繼電器=4,玩家名=andre,為了做成交互式游戲,程序的執(zhí)行順序要更靈活,不只是從上往下執(zhí)行,因此我們還要用'控制流語句'??刂屏髡Z句有好幾種,最常見的有if 語句,可以想象成是'如果x為真,那么執(zhí)行y'
。。。。
只要有足夠的規(guī)則,狀態(tài)和紙帶,就可以創(chuàng)造出任何東西,這就是圖靈機。圖靈機回答了可判定行問題。圖靈機可以實現任何計算,但是'停機問題'圖靈機證明了是無法實現的,所以不是所有問題都能用計算解決的。也就是計算是有極限的,也就是計算機的能力是有限的。
圖靈完備:現在計算機系統(tǒng),比如筆記本電腦,智能手機,甚至微波爐和恒溫器內部的小電腦,都是圖靈完備的。