計算機系統(tǒng)要素(3)— Machine Language

這是計算機組成元素:從零開始構(gòu)建計算機的第三篇總結(jié)铣鹏,對應(yīng)著書本的第四章鲜锚,該章節(jié)主要講述了 Machine Language事哭,即匯編語言狈定。這里我們主要討論匯編是如何通過 processor 和 registers 來處理 memory颂龙。

首先习蓬,我們先分別來看下 memory,processor 和 register 是什么措嵌。

Memory:我們把所有能存儲數(shù)據(jù)與指令的設(shè)備都稱為 memory躲叼。有點類似我們寄存器的結(jié)構(gòu),就是由一個一個的字組成企巢,每個字有一個地址枫慷。一般該地址所指向的值我們用 Memory[address] 來表示。

Processor:一般我們稱為 CPU浪规。CPU 可以執(zhí)行一些 operations或听,比如說,算術(shù)運算和邏輯運算笋婿,memory access誉裆,分支(類似 if-else 語句)。

Registers:這里的寄存器跟 memory 是類似的缸濒,只是這里特指 CPU 上的 Memory足丢。因為 memory access 是一個相對耗時的操作,所以呢就在 CPU 上設(shè)置一些存儲空間绍填,這樣可以滿足 CPU 即想存儲一些值霎桅,又能快速取得這些值的需求。我想 這里的 register 和 Memory 結(jié)構(gòu)肯定有所不同讨永,只是細(xì)的我還沒有去研究滔驶,所以暫時還不知道區(qū)別在那里。

接下來我們講講匯編卿闹。匯編本質(zhì)上是一串 01 的數(shù)字揭糕,只是規(guī)定了一些要求,讓這串?dāng)?shù)字的可讀性大大提高锻霎。比如說一串16位的指令著角,前幾位代表操作符,中間幾位代表操作數(shù)旋恼,等等這樣類似的規(guī)則吏口。這些根據(jù)不同的硬件和匯編語法規(guī)則,具體的要求都會有所差別冰更。

有了規(guī)定产徊,都是數(shù)字還是非常難以讓人理解啊。所以呢有出現(xiàn)了 符號 助記符蜀细。舉例來說舟铜,我又一個寄存器,它的地址是0奠衔,那我同時又可以設(shè)定 R0 ?也代表這個寄存器谆刨。那這個寄存器就有兩種表示方法了塘娶,一個是地址0,另一個就是R0痊夭,哪一種更容易閱讀是非常顯而易見的刁岸。

計算機中,將這種匯編語言轉(zhuǎn)化為最終計算機執(zhí)行的二進(jìn)制碼的是匯編器她我,我們后面幾章將會討論如何實現(xiàn)一個匯編器难捌。不同的硬件設(shè)備就有可能有不同的匯編語言的語法。這一章我們討論的都是一些通用的匯編指令鸦难。

1. 算術(shù)和邏輯運算

就是加減法根吁,與或非這幾種操作。

ADD R2, R1, R3 // ?R2 <—R1 + R3合蔽,R1,R2,R3 都表示寄存器

AND R1, R2, R3

2. Memory Access

Memory Access 有兩種方式:

(1)第一種我們已經(jīng)看到了击敌,就是上面 ADD R2,R1,R3 。進(jìn)行加法運算的時候拴事,我們獲取了 R2 和 R1 中的值沃斤,并將結(jié)果存進(jìn)了 R3。這是一種 memory access刃宵。這是操作于寄存器上的 memory access衡瓶。?

(2)第二種就是利用 load 和 store command。這種指令用于在寄存器和 memory 之間移動數(shù)據(jù)的牲证。這種類型的指令會使用幾種不同的尋址模式哮针,即如何確定我們想要找的字在 memory 中的地址,我們剛說過一個 字對應(yīng)一個地址坦袍。不同的計算機可能會提供不同的尋址模式十厢,但是有三種是都支持的。

? ? ? ? ?— ?直接尋址:比如說我們已經(jīng)知道了地址是 67捂齐,那直接 LOAD R1,67 // R1<- ? ? Memory[67]

? ? ? ? ?— ?立即尋址:這種尋址模式是用于加載常量蛮放,這里的常量不是數(shù)據(jù)常量,而是某個指令的地 址奠宜。比如說:LOADI R1包颁,67 ? ? ? // R1 <— 67

? ? ? ? ?— ?間接尋址:這種尋址模式常見于指針。即寄存器擁有的是指向某一塊地址的指針压真。比如說:LOAD* R2, R1 ? ? ? // ? R2 <— Memory[R1]

3. Flow of Control

?程序通常是順序執(zhí)行的娩嚼,一條接著一條執(zhí)行的。但是有時候會程序會出現(xiàn)分支榴都,出現(xiàn)分支的原因一般有如下三種:

(1)循環(huán)

(2)conditional execution(if-else)

(3)subroutine calling (調(diào)用函數(shù))

為了滿足這種分支待锈,所有的匯編語言提供了跳轉(zhuǎn)的命令(包括有條件和無條件的跳轉(zhuǎn))漠其。這里舉兩個跳轉(zhuǎn)命令的例子嘴高,詳細(xì)的我們后面會介紹竿音。JMP 是無條件跳轉(zhuǎn)的一種,只要你確定了要跳轉(zhuǎn)的地址拴驮,它就直接跳轉(zhuǎn)了春瞬。JNG 是帶條件判斷的一種,只有條件為真才去跳轉(zhuǎn)到指定的地址套啤。

4. Hack Computer

剛我們說過宽气,不同的計算機會有不同的匯編語言,我們這里引進(jìn) Hack Computer潜沦,它跟我們普通的計算機沒什么不同萄涯,只是它簡化了很多東西,同時這個理想化的計算機唆鸡,可以為我們的練習(xí)提供方便涝影,第五章我們要實現(xiàn)的就是這樣一個計算機。

先來簡單介紹下硬件組成:16位的機器争占,一個CPU燃逻,兩塊獨立的存儲空間,一塊存指令臂痕,一塊存數(shù)據(jù)伯襟,一個鍵盤和一個屏幕。

先來介紹下存儲空間的分配握童。剛說了姆怪,一塊指令的 memory 和另一塊 data memory。這兩塊的 memory 都是 16 位寬澡绩,用 15 位地址表示片效。CPU只能執(zhí)行在指令存儲區(qū)的程序,但是指令存儲區(qū)是一塊只能讀取的區(qū)域英古,所以程序只能用外部手段淀衣,而且只能 load 一次。

接下來說下 寄存器召调。Hack Programmer 有兩類寄存器膨桥。一類是 D型寄存器,另一類是 A型寄存器唠叛。兩者的寄存器用作不同的目的只嚣,D型寄存器只是用來存儲數(shù)據(jù)的,而 A型寄存器既可以存數(shù)據(jù)也可以存儲地址艺沼,這里的地址包括數(shù)據(jù)的地址或者是一條指令的地址册舞。

說完這些,就可以講講 Hack Computer 上匯編語言的語法障般。我們剛講過匯編語言都支持三種類型的指令调鲸,Hack Computer 上的當(dāng)然也支持盛杰。

首先是邏輯與算術(shù)運算。沒有用 ADD 這樣的符號去代替藐石,而是依舊 采用 + ,- 等數(shù)學(xué)公式上常用的符號(乘和除還沒有這本書到現(xiàn)在為止都還沒講過即供,不過這章用的解決的一個方法是,累加代替乘)于微。

在接下來是 Memory Access逗嫡。在 Hacker Computer 中,你可以直接獲取到 D型寄存器的值和A型寄存器的值(如果 A 是作為數(shù)據(jù)存儲的功能)株依,比如說 D = xxxx 或者 A = xxxx驱证。其次當(dāng) A 型寄存器是作為地址的是時候,要取得該地址指向的值恋腕,用的是 M雷滚。把兩者結(jié)合起來舉個例子,D = M + 1吗坚, 如果當(dāng)寄存 A 的值是 516 時祈远,這個例子其實就是 D = Memory[516] - 1(真是跟指針一摸一樣)。我們剛說過 A型寄存器還有一個作用是作為指令的地址商源,這里主要是在跳轉(zhuǎn)的時候要用到车份,Hacker Computer 的跳轉(zhuǎn)指令首先要確定跳轉(zhuǎn)到哪里,這個就是由 A型寄存器的值牡彻。所以一般來說扫沼,在我們做跳轉(zhuǎn)之前,都要給 A型寄存器賦值庄吼,來告訴CPU跳轉(zhuǎn)到哪缎除,或者說下條要執(zhí)行的指令的地址在哪里。

指令語法

現(xiàn)在給出指令的具體語法:

A-Instruction

A-instruction,又稱 address instruction总寻,是專門用來給 A 型寄存器設(shè)置值的(剛我們講過 Hack Computer 的計算機設(shè)定了器罐,用 15 位的來表示地址),第一位表示該指令是 A-instruction渐行。

A-instruction:的目的有三個:

(1)這是唯一一個可以直接加載常量的指令轰坊。

(2)提供數(shù)據(jù)地址

(3)提供指令地址

接下來介紹最重要的一個指令

C-instruction

介紹下C-instruction 的用法和意思∷钣。可以看出二進(jìn)制碼對應(yīng)著三個部分(不包括最前面的三面)肴沫。第一位 1 表示該指令是 C-instruction,后面兩位是沒有用到的蕴忆,但是書上沒說能否是0颤芬,所以我們還是用1去寫。

接下來是 compution(comp) 部分。這部分的二進(jìn)制碼指定我們要計算誰站蝠,我們是去D型寄存器去那汰具,還是去取 M 的值,要用什么操作沉衣,是加法還是減法等等。

comp 對照表

第二部分是 destination(dest) 部分减牺⊥阆埃看這名字應(yīng)該就知道這部分的指令是干什么的了,ALU 算出來的結(jié)果放哪去拔疚。

dest 對照表

第三部分就是 jump 部分肥隆。這里的要注意的是,這部分代碼決定的是代碼的跳轉(zhuǎn)是有條件的還是無條件的稚失,其次有條件的跳轉(zhuǎn)是什么樣的條件栋艳。要跳轉(zhuǎn)去哪,是由 A型寄存器決定的句各。

jump 對照表

所以在做跳轉(zhuǎn)指令的時候吸占,一般都要利用下A-instruction,先加載下一條要執(zhí)行的指令的位置是哪凿宾。

書上的例子


可以看到的是在寫跳轉(zhuǎn)指令的時候矾屯,最前面的 dest 部分是不寫的,因為我們已經(jīng)通過 A 型寄存器獲取到了 destination初厚。

有一點要注意件蚕,因為A既可以去做數(shù)據(jù)存儲,也可以做地址存儲产禾,所以很容易分不清楚 A型寄存器到底是干什么的排作。為了防止混淆,在跟跳轉(zhuǎn)有關(guān)的指令的時候亚情,禁止寫M妄痪。

符號

一個常量既可以用數(shù)字表示,也可以用符號表示楞件。在 Hacker Computer 中有三種類型的 symbols拌夏。

(1)predefined symbols。先前計算機就定義好的履因,內(nèi)置的符號障簿。屬于這種的有 :

? ? ?Virtual registers:R0 ~ R15,代表16個寄存器栅迄,和它們的地址

? ? Predefined pointers: SP站故,LCL,ARG,THIS西篓,THAT 代表地址 0 ~4

? ?I/O pointers:SCREEN 和 KBD 表示 鍵盤和屏幕的地址

(2)Label symbols愈腾。當(dāng)然我們也可以自定義。

(XXX) ?// ?這就是語法了岂津,這個你自己定義的 Symbol 就代表了某一個地址

需要注意的是虱黄,你不一定要先定義在使用,你可以先使用吮成,在使用之后在去定義它橱乱,但是你只能定義一次,而不能重復(fù)使用粱甫。

(3)Variable symbols泳叠。任何你沒定義過的 label 就是一個 Variable symbol,會被匯編器任意符一個地址茶宵,從16開始的(前面有 R1 - R15)危纫。

輸入輸出的處理

我們之前提到過 Hacker Computer 有一個鍵盤和屏幕作為輸入輸出設(shè)備。Hacker Computer 與這兩個設(shè)備的交互乌庶,其實是對這兩個設(shè)備對應(yīng)的 memory 作讀寫操作种蝶,這種處理方式叫做 memory map。我們來看下這兩個設(shè)備的 memory瞒大。

(1)Screen:是一塊黑白屏幕蛤吓。分辨率是 256 * 512,每一行由 32 個 16位的字構(gòu)成糠赦,所以是 一位 對應(yīng)著 一個像素點会傲。當(dāng)某一位是 0 時,決定了該像素點顯示白色拙泽,1 則顯示黑色淌山。在 Symbol 那一節(jié),我們看到過系統(tǒng)有個預(yù)定義的符號顾瞻,SCREEN泼疑。這個符號表示的就是屏幕最左上角的那個像素點對應(yīng)的在內(nèi)存中的地址,這個 symbol 值是 16384(0x4000)荷荤。例子如下:

書上例子

這里其實會把最左邊的16個像素全部變?yōu)楹谏?/p>

(2)Keyboard:鍵盤也有一個符號表示退渗,KBD。這個值是 24576(0x6000)蕴纳。其實你算下会油,剛好就是就是在屏幕最后一個像素點的內(nèi)存位置后面一位,256 * 32 + 16384 = 24576古毛。然后 RAM[24576] 的值就是你敲的那個鍵的 ASCII 碼翻翩。沒有鍵按下都许,就是0了。

地址分配

每個存儲在指令存儲區(qū)的指令嫂冻,都會分配一個地址胶征。那匯編器是如何分配的呢?我們這里簡單的就把指令所在的行數(shù)定義為該指令的地址桨仿。這里的行數(shù)是忽略空的行數(shù)的結(jié)果睛低。我們寫程序為了可讀性把空行加上,匯編器不會管這個的服傍。

總結(jié)

現(xiàn)在看下來钱雷,Hack Computer 上的匯編語言非常簡單,總共就兩類指令伴嗡。但實際上一般的匯編語言肯定有更多的數(shù)據(jù)類型急波,更多的寄存器與指令格式从铲。而且這兩類指令其實非常接近高級語言了瘪校,也不是那么的難以讀懂。但是很懂東西本質(zhì)都是一樣的名段,這樣做只是利于我們更好的理解與學(xué)習(xí)阱扬。

文章有任何問題也歡迎指出,還有最重要的一點伸辟,所有的詳細(xì)資料都在:

www.nand2tetris.org/

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末麻惶,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子信夫,更是在濱河造成了極大的恐慌窃蹋,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,997評論 6 502
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件静稻,死亡現(xiàn)場離奇詭異警没,居然都是意外死亡,警方通過查閱死者的電腦和手機振湾,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,603評論 3 392
  • 文/潘曉璐 我一進(jìn)店門杀迹,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人押搪,你說我怎么就攤上這事树酪。” “怎么了大州?”我有些...
    開封第一講書人閱讀 163,359評論 0 353
  • 文/不壞的土叔 我叫張陵续语,是天一觀的道長。 經(jīng)常有香客問我厦画,道長绵载,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,309評論 1 292
  • 正文 為了忘掉前任,我火速辦了婚禮娃豹,結(jié)果婚禮上焚虱,老公的妹妹穿的比我還像新娘。我一直安慰自己懂版,他們只是感情好鹃栽,可當(dāng)我...
    茶點故事閱讀 67,346評論 6 390
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著躯畴,像睡著了一般民鼓。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上蓬抄,一...
    開封第一講書人閱讀 51,258評論 1 300
  • 那天丰嘉,我揣著相機與錄音,去河邊找鬼嚷缭。 笑死饮亏,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的阅爽。 我是一名探鬼主播路幸,決...
    沈念sama閱讀 40,122評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼付翁!你這毒婦竟也來了简肴?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,970評論 0 275
  • 序言:老撾萬榮一對情侶失蹤百侧,失蹤者是張志新(化名)和其女友劉穎砰识,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體佣渴,經(jīng)...
    沈念sama閱讀 45,403評論 1 313
  • 正文 獨居荒郊野嶺守林人離奇死亡辫狼,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,596評論 3 334
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了观话。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片予借。...
    茶點故事閱讀 39,769評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖频蛔,靈堂內(nèi)的尸體忽然破棺而出灵迫,到底是詐尸還是另有隱情,我是刑警寧澤晦溪,帶...
    沈念sama閱讀 35,464評論 5 344
  • 正文 年R本政府宣布瀑粥,位于F島的核電站,受9級特大地震影響三圆,放射性物質(zhì)發(fā)生泄漏狞换。R本人自食惡果不足惜避咆,卻給世界環(huán)境...
    茶點故事閱讀 41,075評論 3 327
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望修噪。 院中可真熱鬧查库,春花似錦、人聲如沸黄琼。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,705評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽脏款。三九已至围苫,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間撤师,已是汗流浹背剂府。 一陣腳步聲響...
    開封第一講書人閱讀 32,848評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留剃盾,地道東北人腺占。 一個月前我還...
    沈念sama閱讀 47,831評論 2 370
  • 正文 我出身青樓,卻偏偏與公主長得像万俗,于是被迫代替她去往敵國和親湾笛。 傳聞我的和親對象是個殘疾皇子饮怯,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,678評論 2 354

推薦閱讀更多精彩內(nèi)容