CPU內(nèi)部的寄存器,機器代碼指令集以及指令與寄存器和狀態(tài)標志的交互方式都是相互交織的。
您可能還記得,我的背景愛好項目之一是構(gòu)建4位HRRG計算機。在整個時間范圍內(nèi),這將實現(xiàn)為壁掛式玻璃前木柜的集合,每個木柜都包含計算機的一部分。每個機柜的功能將通過不同的實施技術(shù)實現(xiàn),包括繼電器,真空管,晶體管和軟糖集成電路,以及磁,機械和氣動/液壓產(chǎn)品。
我在這個項目上的“犯罪伙伴”是我的好友EEWeb專家Joe Farr。Joe致力于創(chuàng)建將在PC上運行的計算機的虛擬表示形式。我們希望能夠在不久的將來使此HRRG仿真器可供任何人使用。同時,我目前正在討論“野獸”的物理實現(xiàn)。
實話實說,這個項目已經(jīng)擱置了相當長的時間。實際上,直到我的好友James“ Chewy” Vorman才在2018年底向我發(fā)送電子郵件,說他正計劃建造4位計算機,并詢問我是否對喬和我當時的指令集有任何想法。促使他們采取行動。
在今年年初,我在“初次通過指令集”上發(fā)布了一篇專欄文章,這幾乎是喬和我在時間的迷霧中留下的東西的地方。從那時起,我們一直在反復地反復提出想法。除此之外,Joe啟動并運行了仿真器后,他很快就厭倦了用機器代碼編寫和輸入測試程序,這促使他創(chuàng)建了一個笨拙的HRRG終端和HRRG匯編器。
運行HRRG匯編程序的HRRG終端。(來源:喬·法爾)
當然,這不是真正的Sperry Univac Uniscope 200,它只是Joe決定將其朋友好友收藏中的一個圖像用作HRRG終端的背景,該終端(在此屏幕快照中)正在運行HRRG匯編程序。當我問喬為什么選擇這種設(shè)備時,他回答說有兩個原因。首先是右側(cè)的面板為他提供了足夠的空間來添加7段LED,常規(guī)LED,開關(guān),磁盤驅(qū)動器和紙帶打孔器的圖像(老實說,我什至沒有意識到這些不是物理設(shè)備的一部分);第二個原因是他太懶了,無法在自己的車間里搜尋成堆的設(shè)備來追蹤他的舊DEC VT100終端。
關(guān)鍵是,在創(chuàng)建諸如井字游戲(Tic-Tac-Toe)之類的程序時(如上面的屏幕截圖所示),喬發(fā)現(xiàn)我們的指令集提供了比我們完全掌握的功能更多的功能(這就是我們的優(yōu)勢)。他還發(fā)現(xiàn)了一些需要“調(diào)整”以使情況變得更好的事情,例如當將INC和DEC指令應用于IX(索引)寄存器之類的12位寄存器時,它們會修改N狀態(tài)標志。
因此,為了使您了解最新信息,以下內(nèi)容將介紹HRRG的CPU寄存器和指令集的當前運行狀態(tài)。
CPU寄存器
請記住,HRRG具有4位數(shù)據(jù)總線和12位地址總線。另外,我們使用術(shù)語nybble(或半字節(jié))來指代4位值;同樣,我們使用“ $”字符表示十六進制值(例如,$ A),使用“%”字符表示二進制值(例如,%1010)。
為了使程序保持“均值”,我們決定將用戶可訪問的寄存器限制為1個半字節(jié)標識符,這意味著我們將自己限制為僅16個寄存器,如下所示:
CPU寄存器(來源:Max Maxfield)
一些早期的8位CPU具有一個稱為累加器(ACC)的特殊寄存器,該寄存器從內(nèi)存中加載值,并存儲邏輯和算術(shù)運算的任何結(jié)果。其他CPU有兩個累加器ACCA和ACCCB,而其他CPU選擇了一堆通用寄存器。在我們的案例中,我們決定有六個通用4位寄存器R0至R5。我們還有兩個狀態(tài)寄存器S0和S1。
除了物理尋址邏輯寄存器PC,SP,IX,IV和TA外,我們還有三個虛擬寄存器CV,MD和MX。我們將看到這些虛擬寄存器如何在整個時間范圍內(nèi)發(fā)揮其魔力??梢哉f我還沒有在其他任何地方見過像我們的虛擬寄存器概念這樣的東西。
狀態(tài)寄存器
如前所述,HRRG具有兩個狀態(tài)寄存器S0和S1。這些寄存器的內(nèi)容如下所示。
狀態(tài)寄存器(來源:Max Maxfield)
大多數(shù)微處理器具有多個跳轉(zhuǎn)指令,例如JMP(無條件跳轉(zhuǎn)),JPN(如果為負則跳轉(zhuǎn)),JPNN(如果不是負則跳轉(zhuǎn)),JPZ(如果為零則跳轉(zhuǎn)),JPNZ(如果不為零則跳轉(zhuǎn))等等。但是,通常只有一條JSR(跳轉(zhuǎn)到子例程)指令。
對于HRRG,我們只有一對JMP(跳轉(zhuǎn))和JSR(跳轉(zhuǎn)到子例程)指令。但是,正如我們將看到的,這些指令的一個很酷的事情是它們的跳轉(zhuǎn)/不跳轉(zhuǎn)動作可以由兩個狀態(tài)寄存器中任何位的0/1值控制(在這種情況下, JMP和JSR指令將兩個4位狀態(tài)寄存器視為單個8位寄存器)。
N,Z,C和O標志以通常的方式運行(對于初學者,我們將在以后的專欄中更詳細地討論這些標志的操作)。
I(中斷屏蔽)標志的狀態(tài)決定了CPU是否將看到并響應外部中斷:此標志中的0表示CPU將不響應;否則標志將變?yōu)?。該標志中的1表示CPU將響應。該標志加電時包含0,由用戶(即用戶的程序)將其設(shè)置為1。如果CPU復位,則該標志將被清除為0。
H(停止)標志指示CPU是運行還是停止:該標志中的0表示CPU將運行;否則,CPU停止運行。該標志中的1表示CPU將停止操作。該標志加電包含0。由用戶決定是否在程序控制下將其設(shè)置為1。使暫停標志返回0的唯一方法是復位CPU或外部中斷喚醒CPU(假定中斷屏蔽標志設(shè)置為1)。
關(guān)于狀態(tài)寄存器S1的位2和3(組合的8位寄存器的位6和7)中的硬連接0和1值,如果選擇了1,則JMP和JSR指令將使用這些值來實現(xiàn)無條件跳轉(zhuǎn),如果選擇了0,則為無條件跳轉(zhuǎn)(用于調(diào)試目的)。
指令集
這是開始變得有趣的地方,因為這是我們決定要支持的低級指令以及這些指令將如何與CPU寄存器和狀態(tài)標志交互的地方。
指令集。(來源:馬克斯·麥克菲爾德(Max Maxfield)
我知道,我知道,當您第一次看到它時,這確實有些令人生畏,但這主要是因為我們正試圖將大量信息塞入一個很小的空間中。
假設(shè)我們要減少通用寄存器R3的4位內(nèi)容。在這種情況下,我們的指令將包含兩個半字節(jié):$ 1 $ 3,我們可以將其寫為$ 13,其中$ 1是DEC(減量)指令的操作碼,而$ 3是指定寄存器R3的
現(xiàn)在假設(shè)我們要增加12位地址為$ 123的存儲單元的4位內(nèi)容。在這種情況下,生成的機器代碼將是$ 0 $ E $ 1 $ 2 $ 3,我們可以將其寫為$ 0E123,其中$ 0是INC(增量)指令的操作碼,$ E是
作為當前的最后一個示例,讓我們假設(shè)我們想將%1010的值(十六進制的$ A)移動(復制)到內(nèi)存位置$ 324中。在這種情況下,生成的機器代碼將為$ F $ D $ E $ A $ 3 $ 2 $ 4,我們可以將其寫為$ FDEA321,其中$ F是MOV(移動)指令的操作碼,$ D是
我們將在接下來的兩列中回顧這些機器代碼指令和等效的匯編語言(相信我,當我們開始考慮匯編語言時,情況會變得更加清晰)。目前,請仔細閱讀并仔細考慮以下注意事項(其編號與上表中的編號匹配),其中對這些內(nèi)容進行了非常詳細的總結(jié)。
#1如果源是CPU的4位或12位物理寄存器之一,則不會有
#2如果源是存儲位置(使用MD或MX虛擬寄存器指示),則
#3如果源是一個常量值(如CV虛擬寄存器所示),則如果目標是4位寄存器或存儲位置,則
#4如果目標是CPU的4位或12位物理寄存器之一,則不會有
#5如果目標是內(nèi)存位置(如使用MD或MX虛擬寄存器指示的),則
#6如果源是4位寄存器,則目標通常是4位寄存器或存儲器位置;否則,目標將是4位寄存器或存儲位置。如果源是4位寄存器,而目標是12位寄存器(PC,SP,IX,IV,TA)之一,則4位寄存器的內(nèi)容將被移入(復制)到最小-目標寄存器的顯著半字節(jié)(LSN);如果源是12位寄存器之一(PC,SP,IX,IV,TA),則目標通常是12位寄存器或存儲器位置(請參閱注釋7);如果源是12位寄存器,而目標是4位寄存器,則12位寄存器的LSN的內(nèi)容將被復制到4位寄存器中。
#7如果將12位寄存器的內(nèi)容復制到內(nèi)存中,則目標操作數(shù)將是3個半字節(jié)字段的最低有效地址。如果將存儲器的內(nèi)容復制到12位寄存器中,則源操作數(shù)將是3個半字節(jié)字段的最低有效地址。
#8如果源是4位寄存器或存儲器位置,則將1個半字節(jié)值壓入堆棧,并且SP = SP +1;如果源是12位寄存器,則將3個半字節(jié)值壓入堆棧,并且SP = SP + 3;按下PUSH之后,堆棧指針將遞增。
#9如果源是一個常數(shù)值,則源操作數(shù)將是1個半字節(jié)值,該值將被壓入堆棧,并且SP = SP + 1(在PUSH之后堆棧指針將遞增)。
#10如果目標是4位寄存器或內(nèi)存位置,則SP = SP – 1且將向堆棧彈出一個1字節(jié)的值(即,堆棧指針將在POP之前遞減)。如果目標是一個12位寄存器,則將從堆棧中彈出一個3位值(以SP = SP – 3結(jié)尾)。
#11沒有RTS(“從子程序返回”)或RTI(“從中斷返回”)指令–通過使用POP指令從堆棧中檢索返回地址并將其加載到PC中,可以達到相同的效果。
#12 JMP和JSR指令后跟控制小節(jié),然后是3小節(jié)目標地址??刂瓢胱止?jié)用于執(zhí)行無條件跳轉(zhuǎn)或有條件跳轉(zhuǎn)。控制半字節(jié)的最低有效三位指向由S1和S0組成的8位狀態(tài)寄存器中的要測試的位;范圍是000到111(0到7)。假設(shè)控制半字節(jié)的最高有效位為0,則所選狀態(tài)位的值為1會導致跳轉(zhuǎn);否則,該值將變?yōu)?。例如,JMP%0001 <目標地址>等效于“如果為零則跳轉(zhuǎn)”。相比之下,控制半字節(jié)最高有效位中的1將反轉(zhuǎn)跳轉(zhuǎn)的操作。例如,JMP%1001 <目標地址>等同于“如果不為零則跳轉(zhuǎn)”。請注意,狀態(tài)位7 [S1中的位3]是硬連線的1,
指令和狀態(tài)寄存器
最后(并非暫時),下表總結(jié)了執(zhí)行各種指令影響狀態(tài)寄存器中標志的方式。
指令和狀態(tài)位(來源:Max Maxfield)
您可以想象,設(shè)計計算機是一個反復的過程,事實證明,擁有Joe的仿真器是無價的。例如,只有當Joe開始編寫一個播放井字游戲的程序時,我們才意識到,使用12-像IX(索引寄存器)這樣的位寄存器,因此我們將其添加到規(guī)范中(在物理實現(xiàn)中僅包含一件事。
以下注釋更詳細地說明了上表的內(nèi)容:
#1將目標值的最高有效位(MSB)復制到C標志中;同時,將C標志的原始內(nèi)容復制到目標值的最低有效位(LSB)。
#2將目標值的最低有效位(LSB)復制到C(進位)標志;同時,將C標志的原始內(nèi)容復制到目標值的最高有效位(MSB)。
#3如果比較的值相等,則Z標志設(shè)置為1,否則將其清除為0。
#4被比較的值被認為是無符號整數(shù)。如果
#5如果目標是狀態(tài)寄存器S1,則將從堆棧中加載其標志,并且不會影響S0的內(nèi)容;如果目標是S0,那么將從堆棧中加載其標志;如果目標是其他任何4位位置(寄存器或內(nèi)存),則N和Z標志將照常運行。
#6這些標志對于4位目標照常工作,但有一個例外-如果目標是狀態(tài)寄存器S0或S1之一,則S0中的標志將不會自動更新;否則,這些標志將自動更新。如果源是12位寄存器,而目標是4位寄存器,則Z和N標志將基于12位寄存器的最低有效字節(jié)的內(nèi)容(即,復制);如果源是12位寄存器,而目標是存儲器,則將基于整個12位寄存器的內(nèi)容設(shè)置Z標志,并且將基于N位的最高有效字節(jié)的內(nèi)容設(shè)置N標志。 12位寄存器。
#7將根據(jù)整個12位寄存器的內(nèi)容設(shè)置Z標志,并根據(jù)12位寄存器的最高有效半字節(jié)的內(nèi)容設(shè)置N標志。
編輯:hfy
-
繼電器
+關(guān)注
關(guān)注
132文章
5314瀏覽量
148318 -
寄存器
+關(guān)注
關(guān)注
31文章
5290瀏覽量
119785 -
cpu
+關(guān)注
關(guān)注
68文章
10802瀏覽量
210746 -
計算機
+關(guān)注
關(guān)注
19文章
7348瀏覽量
87622
發(fā)布評論請先 登錄
相關(guān)推薦
評論