一旦我們構(gòu)建了一臺計算機,下一步就是開發(fā)一種匯編語言,然后是一個可以匯編我們程序的匯編器。
?
在我之前的專欄中,我們介紹了在計算機內(nèi)存中存儲多字節(jié)(或在我們的例子中是多 nybble)數(shù)據(jù)塊的大端與小端方式的概念。我們還概述了計算機設(shè)計者可能決定支持的一些尋址模式。現(xiàn)在是時候開始為我們的 4 位 HRRG 計算機考慮匯編語言和匯編程序了。
另請參閱此索引,該索引列出了構(gòu)成我們的 4 位 HRRG 計算機項目的所有文章,以及一些有趣的相關(guān)專欄。
作為我們討論的起點,讓我們進行一個簡單的思想實驗。假設(shè)我們剛剛完成了 4 位 HRRG 計算機的構(gòu)建。我們還假設(shè)它是地球上的第一臺計算機;也就是說,沒有任何其他計算機,或編程語言,或者……嗯,任何東西,真的。
讓我們對自己大方一點,假設(shè)我們還開發(fā)了一些輸入和輸出設(shè)備——看起來有點像 QWERTY 鍵盤、VT100 終端和紙帶閱讀器/寫入器——并且我們已經(jīng)將它們連接到了一些 HRRG輸入和輸出端口,但我們還沒有創(chuàng)建任何代碼來驅(qū)動小流氓。
在繼續(xù)本專欄的其余部分之前,為什么不暫停片刻來思考您的下一步是什么。
以機器代碼捕獲和輸入程序
作為快速提醒,HRRG 有 16 個寄存器并支持 16 條指令,如下所示(關(guān)于各種指令執(zhí)行其魔法的方式的更詳細(xì)討論在我們的“指令集”和“指令權(quán)衡”列)。
我們的首要任務(wù)是創(chuàng)建一個非常非常簡單的程序,只是為了確保這個野獸能夠正常工作。如果我們決定使用鉛筆和紙來繪制帶有相關(guān)注釋的流程圖來捕捉該程序的意圖,我不會感到驚訝,如下圖所示:
下一步將是計算出我們想要將哪些操作碼和操作數(shù)加載到計算機內(nèi)存中以實現(xiàn)我們的程序。再一次,這可能涉及鉛筆和紙以及一些皺眉和撓頭,導(dǎo)致如下所示:
這種類型的表示被稱為“機器代碼”,因為這些是我們的計算機(機器)將執(zhí)行(處理)的二進制代碼。
最后但并非最不重要的一點是,我們希望將機器代碼加載到我們的計算機中并運行程序,但我們將如何做到這一點?好吧,我們可能會構(gòu)建一個開關(guān)面板并將其連接到計算機。至少,這將涉及 12 個用于表示地址的撥動開關(guān),4 個用于表示數(shù)據(jù)的撥動開關(guān),以及幾個控制開關(guān)和按鈕,如下圖所示。
為了進入程序,我們將“Program/Run”開關(guān)設(shè)置為“Program”,在地址開關(guān)上設(shè)置一個地址,在數(shù)據(jù)開關(guān)上設(shè)置一個相應(yīng)的操作碼或操作數(shù),然后按下“Load”按鈕將此值加載到內(nèi)存中。我們將對構(gòu)成我們程序的所有 nybbles 重復(fù)此過程。上圖顯示我們準(zhǔn)備將 $C(跳轉(zhuǎn))操作碼輸入到內(nèi)存位置 $106。
輸入程序后,我們將地址開關(guān)設(shè)置為指向程序的起始地址(本例中為 100 美元),然后將“程序/運行”開關(guān)切換到“運行”。
用匯編語言捕獲程序
許多設(shè)計原始計算機的團隊認(rèn)為,為了獲得最佳結(jié)果,有必要盡可能靠近機器。也就是說,他們的理念是以盡可能接近機器內(nèi)部表示的形式編寫程序;即機器碼。
然而,正如您可能想象的那樣,以機器代碼捕獲和輸入程序是耗時的、容易出錯的,并且——最終——在下面的區(qū)域中是一種痛苦。抽象階梯的下一步是用稱為匯編語言的低級符號編程語言捕獲程序,其中程序語句和計算機的機器代碼指令之間存在非常強的對應(yīng)關(guān)系。(英國數(shù)學(xué)家 Kathleen Booth 根據(jù)她 1947 年開始的理論工作發(fā)明了匯編語言的概念。)
當(dāng)然,擁有匯編語言與擁有匯編程序不同,匯編程序一詞是指將匯編源代碼轉(zhuǎn)換為可執(zhí)行機器代碼的實用程序。在我們的思想實驗中,我們?nèi)蕴幱谑褂勉U筆和紙捕捉程序的階段。
假設(shè)我們已經(jīng)定義了 HRRG 匯編語言(我們將在下一篇專欄中更詳細(xì)地討論這種語言)。在這種情況下,我們可以使用鉛筆和紙以匯編語言捕獲我們的程序,并將其手動組裝成機器代碼。讓我們考慮一下在我們的原始測試程序的情況下這可能是什么樣子,如下圖所示:
非常有用的一件事是將標(biāo)簽與關(guān)鍵指令的地址相關(guān)聯(lián),例如標(biāo)記循環(huán)開始的 LOOP 標(biāo)簽。在執(zhí)行程序時,我們將構(gòu)建一個標(biāo)簽及其地址的交叉引用表,如上圖右上角所示。
對于我們的簡單程序,我們在使用標(biāo)簽之前聲明了它們,這讓我們的生活變得輕松。在一個更復(fù)雜的程序中,我們可能會在聲明它之前引用一個標(biāo)簽(例如,跳轉(zhuǎn)到一個標(biāo)簽位于程序下方的子程序)。在這種情況下,我們將對源代碼執(zhí)行多次遍歷,其中第一次遍歷允許我們確定所有標(biāo)簽的地址,第二次遍歷允許我們解析第一次不知道的任何地址-時間循環(huán)。
通過我們的引導(dǎo)來提升自己
這就是事情開始變得有趣的地方。首先,我們將創(chuàng)建幾個簡單的低級實用程序,以允許我們監(jiān)控鍵盤并使用我們的紙帶閱讀器/寫入器。我們將通過用鉛筆和紙捕獲源代碼,將其手工組裝成機器代碼,然后使用我們的開關(guān)面板將機器代碼加載到計算機的內(nèi)存中來做到這一點(請注意,我們可以將多個程序存儲在記憶)。
大約在這個時候,我們還將創(chuàng)建一個低級監(jiān)控程序。這樣的程序提供了一個簡單的用戶界面——通?;趩巫址睢栽试S用戶執(zhí)行檢查和更改內(nèi)存、讀取或?qū)懭?I/O 端口以及將控制權(quán)轉(zhuǎn)移到內(nèi)存中的其他程序等操作。再一次,該程序?qū)⑹褂勉U筆和紙捕獲,手工組裝,并使用開關(guān)面板加載到計算機的內(nèi)存中。
接下來,我們將創(chuàng)建一個簡單的匯編程序,僅支持我們最終希望擁有的功能的一個子集。和以前一樣,這個簡單的匯編程序?qū)⑹褂勉U筆和紙來捕獲,手工組裝,然后使用開關(guān)面板加載到計算機的內(nèi)存中。
現(xiàn)在我們準(zhǔn)備好搖滾了,因為我們可以使用類似電傳終端的東西來捕獲我們的第一遍匯編器支持的匯編語言子集中的程序,并將這些源代碼程序?qū)懭爰垘А?/font>接下來,我們可以使用監(jiān)控程序和我們的實用程序從紙帶中讀取此源代碼并將其存儲在計算機內(nèi)存的一個區(qū)域中。然后我們可以使用我們的第一遍匯編器將這個源代碼匯編成可執(zhí)行的機器代碼并將其存儲在另一個內(nèi)存區(qū)域中。此時,我們可以對存儲在計算機內(nèi)存中的可執(zhí)行機器代碼做兩件事:
例如,交叉匯編器是一種匯編器,它可以將指令轉(zhuǎn)換為計算機的機器代碼,而不是運行它的計算機。我在 HRRG 上的同謀,EEWeb 專家 Joe Farr,創(chuàng)建了一個在 PC 上運行的 HRRG 交叉匯編器,它采用 HRRG 的匯編語言編寫的程序,并生成可執(zhí)行的機器/目標(biāo)代碼以在 HRRG 上運行。下面的兩張圖片顯示了同一程序片段的源代碼和目標(biāo)代碼版本。
?

HRRG 交叉匯編源代碼查看(來源:Joe Farr)
?
?

HRRG 交叉匯編器目標(biāo)代碼視圖(來源:Joe Farr)
?
更棒的是,HRRG的匯編器是一個宏匯編器,它是一個可以進行宏替換和擴展的匯編器。這允許我們定義由一個或多個語句組成的宏,然后在程序中稍后使用這些宏名稱,從而避免重寫語句。
舉個簡單的例子,HRRG 的指令集不包含 HALT 指令。但是,我們可以在 HRRG 的匯編語言中將這樣的指令實現(xiàn)為宏,如下所示:
.MACRO HALT
OR %0010, S1
.ENDMACRO
現(xiàn)在,我們可以將前面程序示例中的 OR 指令替換為 HALT,這有助于使程序更易于理解。此外,我們可以將所有宏捆綁到一個單獨的文件中,我們可以使用 .INCLUDE 指令將其導(dǎo)入到我們的程序中。
在我的下一篇專欄中,我們將研究 HRRG 的匯編語言,我們還將考慮如何使用宏來實現(xiàn) HRRG 本身不支持的一堆指令,例如 ADD、SUB、ROL、ROR、ASHL 、ASHR、LSHL 和 LSHR。與此同時,我一如既往地歡迎您提出意見和問題。
審核編輯 黃昊宇
評論