如果您將自己限制在只有 16 條指令,您應(yīng)該選擇哪些指令,如果沒(méi)有那些被擱置的指令,您將如何管理?
在我之前關(guān)于從頭開始構(gòu)建 4 位 HRRG(Heath Robinson,Rube Goldberg)計(jì)算機(jī)項(xiàng)目的專欄中,我們介紹了 CPU 寄存器和指令集。您可能還記得,由于我們只有 4 位數(shù)據(jù)總線(以及 12 位地址總線),我們選擇只有 2^4 = 16 條指令以及 2^4 = 16 個(gè) CPU 寄存器。
為了確保我們都跟著同一個(gè)鼓點(diǎn)跳舞,讓我們提醒自己,六個(gè)通用寄存器 R0 到 R5 用于存儲(chǔ)數(shù)據(jù)值并“累積”來(lái)自任何算術(shù)或邏輯運(yùn)算的結(jié)果。狀態(tài)寄存器 S0 和 S1 主要用于存儲(chǔ)任何算術(shù)或邏輯運(yùn)算的狀態(tài)結(jié)果,例如減法的結(jié)果是否為零。
另請(qǐng)參閱此索引,其中列出了構(gòu)成我們的 4 位 HRRG 計(jì)算機(jī)項(xiàng)目的所有文章,以及一些有趣的相關(guān)專欄。
程序計(jì)數(shù)器 (PC) 用于跟蹤 CPU 在程序中的當(dāng)前位置。堆棧指針 (SP) 用于跟蹤堆棧的頂部。索引寄存器 (IX) 主要用于保存計(jì)數(shù)值或訪問(wèn)內(nèi)存的偏移量。中斷向量 (IV) 用于保存稱為中斷服務(wù)路由 (ISR) 的特殊類型子程序的內(nèi)存地址。
介紹堆棧指針
我們將在以后的專欄中考慮所有這些小寄存器流氓如何在令人難以忍受的細(xì)節(jié)中發(fā)揮它們的魔力,但如果這對(duì)您來(lái)說(shuō)是新的,那么簡(jiǎn)要描述 SP 的操作可能是個(gè)好主意。
我們大多數(shù)人都去過(guò)自助餐廳,那里有一堆盤子堆疊在一個(gè)彈簧機(jī)構(gòu)的頂部。假設(shè)您是負(fù)責(zé)將板裝入機(jī)械裝置的人員。讓我們還假設(shè)板的編號(hào)為(1、2、3……),并且——作為一個(gè)強(qiáng)迫癥工程師——這是將前三個(gè)板加載到機(jī)制中的順序,如下圖所示:
現(xiàn)在假設(shè)一個(gè)顧客進(jìn)來(lái)拿盤子。當(dāng)然,它們會(huì)檢索您添加到堆棧頂部的最后一個(gè)盤子(在我們的示例中為 3 號(hào))。在計(jì)算方面,這種形式的存儲(chǔ)和檢索將被歸類為后進(jìn)先出 (LIFO)過(guò)程。
好吧,我們的 SP 以類似的方式工作。在我們的程序開始時(shí),我們將使用我們不用于其他任何內(nèi)容的內(nèi)存區(qū)域中某個(gè)位置的地址加載 SP。隨后,我們每次執(zhí)行 PUSH 操作時(shí),CPU 都會(huì)將指定的數(shù)據(jù)寫入 SP 當(dāng)前指向的內(nèi)存位置(“棧頂”),然后將 SP 加一以指向下一個(gè)空閑位置。相比之下,每次執(zhí)行 POP 操作時(shí),CPU 都會(huì)先遞減 SP 以指向堆棧頂部的數(shù)據(jù),然后從堆棧中讀取該數(shù)據(jù)并將其存儲(chǔ)到我們告訴它的任何位置。
介紹 6502
出于以下討論的目的,我們將使用MOS 技術(shù) 6502來(lái)提供比較的基礎(chǔ)。1975 年推出的 6502 有一個(gè) 8 位數(shù)據(jù)總線和一個(gè) 16 位地址總線,其寄存器包括一個(gè) 8 位累加器寄存器(A)、兩個(gè) 8 位索引寄存器(X 和 Y)、一個(gè) 7-位處理器狀態(tài)標(biāo)志寄存器 (P)、一個(gè) 8 位堆棧指針 (S) 和一個(gè) 16 位程序計(jì)數(shù)器 (PC)。
與 HRRG 不同,我們可以將 12 位 SP 加載為我們想要的任何值,6502 的 8 位 SP 在上電時(shí)自動(dòng)加載 $00(請(qǐng)記住,我們使用“$”字符表示十六進(jìn)制值),并且堆棧的起始地址被硬連線到 $0100。這意味著 6502 的堆棧地址空間被限制在 256 個(gè)地址 $0100 到 $01FF 之間。
盡管與今天的微處理器產(chǎn)品相比,6502 看起來(lái)很簡(jiǎn)單,但它在其誕生之初就被認(rèn)為是相當(dāng)了不起的,尤其是因?yàn)樗目沙惺艿膬r(jià)格標(biāo)簽(1975 年為 25 美元)。許多人繼續(xù)基于這款處理器創(chuàng)造出令人驚嘆的項(xiàng)目,例如這款基于 6502 的虛擬現(xiàn)實(shí) (VR) 系統(tǒng)。6502 的新版本不斷出現(xiàn),例如MOnSter 6502 CPU。
此外,與 HRRG 不同的是,我們可以將 12 位中斷向量 (IV) 加載為我們想要的任何值,6502 被硬連線以查看內(nèi)存地址 $FFFE 和 $FFFF 以檢索其 16 位中斷向量,其中這個(gè) 2 字節(jié)的值將由用戶加載到內(nèi)存中(當(dāng)我們說(shuō)“由用戶”時(shí),我們真正的意思是“由用戶的程序”)。
在可用的 2^8 = 256 個(gè)可能的操作碼(指令)中,最初的 6502 使用 151 個(gè)組織成 56 條指令(取決于指令),一種或多種尋址模式。根據(jù)指令和尋址模式,6502 操作碼可能需要 0、1 或 2 個(gè)額外字節(jié)用于操作數(shù);因此 6502 條機(jī)器指令的長(zhǎng)度從 1 個(gè)字節(jié)到 3 個(gè)字節(jié)不等。
MOV(加載和存儲(chǔ))
6502 允許用戶將值從內(nèi)存加載到累加器(A)和索引寄存器(X 和 Y)。同樣,它允許用戶將這些寄存器中的值存儲(chǔ)到內(nèi)存中。所有這些都需要六個(gè)指令,如下所示:
LDA(加載累加器)
LDX(加載 X 寄存器)
LDY(加載 Y 寄存器)
STA(存儲(chǔ)累加器)
STX(存儲(chǔ) X 寄存器)
STY(存儲(chǔ) Y 寄存器)
相比之下,HRRG 有一條 MOV 指令,可用于根據(jù)其操作數(shù)將數(shù)據(jù)從寄存器到寄存器、寄存器到內(nèi)存、內(nèi)存到寄存器和內(nèi)存到內(nèi)存移動(dòng)(復(fù)制)。此外,這些指令適用于所有 HRRG 的寄存器(即使這樣做沒(méi)有意義 - 更多內(nèi)容見下文)。
INC(遞增)和 DEC(遞減)
6502 允許用戶遞增(加 1)和遞減(減 1)指定內(nèi)存位置或其索引寄存器(X 和 Y)中的值。為了做到這一點(diǎn),它需要以下六個(gè)指令:
INC(增加內(nèi)存位置的內(nèi)容)
INX(增加 X 寄存器的內(nèi)容)
INY(增加 Y 寄存器的內(nèi)容)
DEC(減少內(nèi)存位置的內(nèi)容)
DEX(減少 X 寄存器的內(nèi)容)
DEY(減少 Y 寄存器的內(nèi)容)
“增加或減少累加器的內(nèi)容呢?” 我聽到你哭了。好吧,為了使用 6502 實(shí)現(xiàn)這一點(diǎn),您必須執(zhí)行本專欄后面討論的常規(guī)加法或減法運(yùn)算。
相比之下,HRRG 的 INC 和 DEC 指令可用于遞增內(nèi)存位置以及任何 CPU 的 4 位和 12 位寄存器的內(nèi)容。
“什么?任何寄存器——甚至是程序計(jì)數(shù)器?” 我聽到你緊張地尖叫。是的,您可以在任何寄存器上使用這些指令,即使這樣做似乎沒(méi)有意義。例如,增加程序計(jì)數(shù)器 (PC) 通常被認(rèn)為是一件壞事,但 HRRG 允許在機(jī)器代碼和底層硬件中這樣做。
我們可能會(huì)在匯編程序中標(biāo)記某些“愚蠢”(我們將在以后的專欄中討論),但如果用戶決定忽略并繞過(guò)匯編程序發(fā)出的任何警告和/或錯(cuò)誤消息,那么就這樣吧,因?yàn)?(a)在沒(méi)有無(wú)數(shù)例外和特殊情況的情況下設(shè)計(jì)硬件更容易工作,(b)用戶可能會(huì)想出我們沒(méi)有想到的狡猾的使用模型,以及(c)我們不是“明智的警察”(除了別的,我沒(méi)有合適的褲子)。
ADDC 和 SUBB(加法和減法)
當(dāng)我們?cè)诤?jiǎn)單計(jì)算機(jī)的情況下考慮加法時(shí),我們通常會(huì)想到將兩個(gè)數(shù)字相加,例如 3 + 2 = 5。問(wèn)題是我們可以表示的數(shù)字的大小是受限于我們的數(shù)據(jù)總線和數(shù)據(jù)字段的寬度。例如,在 HRRG 的情況下,單個(gè) 4 位 nybble 可用于表示 0 到 15 范圍內(nèi)的無(wú)符號(hào)數(shù)或 -8 到 +7 范圍內(nèi)的有符號(hào)數(shù)。
這顯然有點(diǎn)限制。幸運(yùn)的是,我們可以使用多個(gè) nybbles 來(lái)表示我們的值。例如,在 HRRG 的情況下,一對(duì) 4 位 nybbles 可用于表示 0 到 255 范圍內(nèi)的無(wú)符號(hào)數(shù)或 -128 到 +127 范圍內(nèi)的有符號(hào)數(shù)。
假設(shè)我們想將兩個(gè) 2-nybble 值相加。在這種情況下,我們將從添加兩個(gè)最不重要的 nybbles (LSN) 開始。根據(jù)它們的值,這將導(dǎo)致 0 或 1 值存儲(chǔ)在進(jìn)位 (C) 狀態(tài)標(biāo)志中。當(dāng)我們添加下一對(duì) nybbles 時(shí),我們還需要包含(添加)進(jìn)位標(biāo)志的內(nèi)容。
一些早期的 8 位處理器提供了兩個(gè)加法指令,例如 ADD(“無(wú)進(jìn)位相加”)和 ADDC(“有進(jìn)位相加”)。其他的,比如6502,只提供了“帶進(jìn)位相加”的版本,由用戶自己實(shí)現(xiàn)“不帶進(jìn)位相加”,先將進(jìn)位標(biāo)志加載0,再進(jìn)行相加。
同樣的事情也適用于減法。在這種情況下,一些早期的 8 位處理器提供了兩個(gè)減法指令,例如 SUB(“無(wú)借位減法”)和 SUBB(“有借位減法”)。其他的,比如6502,只提供了“借位減法”的版本,由用戶來(lái)實(shí)現(xiàn)“不借位減法”,首先將進(jìn)位標(biāo)志加載1,然后執(zhí)行減法。
“等一下,我們沒(méi)有借用狀態(tài)標(biāo)志,”我聽到你在嗚咽。這是真的,但在減法的情況下,進(jìn)位 (C) 標(biāo)志承擔(dān)借位 (B) 標(biāo)志的角色?;谖ㄒ坏奈锢順?biāo)志是進(jìn)位標(biāo)志,一些設(shè)計(jì)師更喜歡說(shuō)“有/沒(méi)有進(jìn)位減法”,并使用類似 SUBC 助記符的東西,但是,在我看來(lái),這最終會(huì)導(dǎo)致更多的混亂而不是它的價(jià)值.
底線是 6502 提供了如下兩條指令:
ADC(進(jìn)位加法)
SBC(進(jìn)位減法)
此外,這些指令只允許您將指定內(nèi)存位置的內(nèi)容添加/減去累加器的內(nèi)容,結(jié)果存儲(chǔ)在累加器中。
同樣,HRRH 提供如下兩條指令:
ADDC(進(jìn)位加法)
SUBB(借位減法)
然而,這些指令允許執(zhí)行寄存器到寄存器、寄存器到存儲(chǔ)器、存儲(chǔ)器到寄存器以及存儲(chǔ)器到存儲(chǔ)器的加法和減法。(在我的下一篇專欄中,我們將考慮使用 ADDC 和 SUBB 指令來(lái)實(shí)現(xiàn)其對(duì)應(yīng)的 ADD 和 SUB 的各種方式。)
ROLC 和 RORC(旋轉(zhuǎn)和移位)
可能有八種基本的旋轉(zhuǎn)和移位操作,我們可以為其分配助記符,如下所示:
ROL(左移)
ROR(右移)
ROLC(通過(guò)進(jìn)位標(biāo)志左移)
RORC(通過(guò)進(jìn)位標(biāo)志右移)
LSHL(邏輯左移)
ASHL(算術(shù)左移)
LSHR(邏輯右移)
ASHR(算術(shù)移位正確的)
請(qǐng)記住,不同 CPUS 的設(shè)計(jì)者對(duì)這類事情使用各種不同的助記符;我在上面展示的那些對(duì)我來(lái)說(shuō)最有意義?,F(xiàn)在,如果我們決定(我們沒(méi)有)在我們的 4 位 HRRG 中實(shí)現(xiàn)所有這八個(gè)指令,它們的操作的圖形表示將如下所示:
在 ROL(左移)的情況下,所有位都左移一位;此外,概念上“落下”的最高有效位 (MSB) 被復(fù)制到最低有效位 (LSB) 和進(jìn)位標(biāo)志中。相比之下,在 ROR(左移)的情況下,所有位都右移一位;此外,概念上“落下”的 LSB 被復(fù)制到 MSB 和進(jìn)位標(biāo)志中。
ROLC(通過(guò)進(jìn)位向左旋轉(zhuǎn))與ROL非常相似,只是進(jìn)位標(biāo)志的原始內(nèi)容被復(fù)制到LSB中。類似地,RORC(通過(guò)進(jìn)位向右旋轉(zhuǎn))與ROR非常相似,只是進(jìn)位標(biāo)志的原始內(nèi)容被復(fù)制到MSB中。
LSHL(邏輯左移)操作與ROL(向左旋轉(zhuǎn))和ROLC(通過(guò)catty向左旋轉(zhuǎn))操作非常相似,只是0被復(fù)制到LSB中。類似地,LSHR(邏輯右移)操作與ROR(向右旋轉(zhuǎn))和RORC(通過(guò)進(jìn)位向右旋轉(zhuǎn))操作非常相似,只是0被復(fù)制到MSB中。
ASHL(算術(shù)左移)操作在功能上與LSHL(邏輯左移)相同-兩者都會(huì)導(dǎo)致將0復(fù)制到LSB中-因此沒(méi)有設(shè)計(jì)人員會(huì)費(fèi)心將其作為CPU中的單獨(dú)指令來(lái)實(shí)現(xiàn)。另一方面,在編寫程序時(shí),我們可能更喜歡使用這兩種不同的助記符作為注釋,以提醒自己(和其他讀者)當(dāng)我們捕獲代碼時(shí)的想法。
最后,ASHR(算術(shù)右移)與LSHR(邏輯右移)類似,只是MSB(符號(hào)位)被復(fù)制回自身(另請(qǐng)參閱“C/C++>移位運(yùn)算符的工作原理”)。
在HRRG的情況下,被限制為16條指令,我們決定只實(shí)現(xiàn)八個(gè)基本旋轉(zhuǎn)和移位中的兩個(gè):
ROLC(通過(guò)進(jìn)位標(biāo)志向左旋轉(zhuǎn))
RORC(通過(guò)進(jìn)位標(biāo)志向右旋轉(zhuǎn))
我們選擇這兩條指令的原因是,很容易將它們作為實(shí)現(xiàn)其他指令功能的基礎(chǔ)。(我們將在下一篇專欄文章中考慮使用ROLC和RORC指令實(shí)現(xiàn)其ROL、ROR、LSHL、LSHR、ASHL和ASHR對(duì)應(yīng)項(xiàng)的各種方式。)
AND、OR、XOR 和 CMP(邏輯運(yùn)算)
這些指令的工作方式與地球上幾乎任何其他處理器上的對(duì)應(yīng)指令類似,因此我們不會(huì)在此花太多時(shí)間討論它們??梢赃@么說(shuō),6502 的 AND(邏輯與)、EOR(異或)和 ORA(包括或)僅允許您使用內(nèi)存中保存的另一個(gè)值對(duì)累加器的內(nèi)容執(zhí)行操作,結(jié)果存儲(chǔ)在蓄能器。相比之下,HRRG 的 AND、OR 和 XOR 等效項(xiàng)支持寄存器到寄存器、寄存器到內(nèi)存和內(nèi)存到寄存器操作。
在 HRRG 的 CMP(比較指令)的情況下,它還支持寄存器到寄存器、寄存器到內(nèi)存、內(nèi)存到寄存器和內(nèi)存到內(nèi)存操作,被比較的兩個(gè)值被視為是無(wú)符號(hào)二進(jìn)制值。
CLR 和 SET(位操作操作)
一些處理器提供一套指令,可用于清除或設(shè)置狀態(tài)寄存器中的各個(gè)位。例如,6502 支持七種這樣的指令:
CLC(清除進(jìn)位標(biāo)志)
CLD(清除十進(jìn)制模式標(biāo)志)
CLI(清除中斷禁止標(biāo)志)
CLV(清除溢出標(biāo)志)
SEC(設(shè)置進(jìn)位標(biāo)志)
SED(設(shè)置十進(jìn)制模式標(biāo)志)
SET(設(shè)置中斷禁止標(biāo)志)
HRRG 沒(méi)有提供任何這些說(shuō)明,但如果提供了,他們的基因組學(xué)將如下(我們將看到我的瘋狂是有原因的):
CLRN(清除負(fù)標(biāo)志)
CLRZ(清除零標(biāo)志)
CLRC(清除進(jìn)位標(biāo)志)
CLRO(清除溢出標(biāo)志)
CLRI(清除中斷屏蔽標(biāo)志)
SETN(設(shè)置負(fù)標(biāo)志)
SETZ(設(shè)置零標(biāo)志)
SETC(設(shè)置進(jìn)位標(biāo)志)
SETO(設(shè)置溢出標(biāo)志)
SETI(設(shè)置中斷屏蔽標(biāo)志)
SETH(設(shè)置停止標(biāo)志)
觀察沒(méi)有 CLRH(清除停止標(biāo)志)。這是因?yàn)橐坏和?biāo)志設(shè)置為 1,重置它的唯一方法是觸發(fā)中斷(假設(shè)中斷屏蔽標(biāo)志設(shè)置為 1)或重置機(jī)器。
關(guān)鍵是我們可以使用 AND 和 OR 邏輯運(yùn)算來(lái)實(shí)現(xiàn)所有這些指令。假設(shè)我們想將進(jìn)位標(biāo)志(狀態(tài)寄存器 S0 中的第 2 位)清除為 0,我們可以通過(guò)將 S1 的內(nèi)容與 %1011 進(jìn)行“與”運(yùn)算來(lái)做到這一點(diǎn)(請(qǐng)記住,我們使用 '%' 字符來(lái)表示二進(jìn)制值)。類似地,如果我們想將進(jìn)位標(biāo)志設(shè)置為 1,我們可以通過(guò)將狀態(tài)寄存器 S0 的內(nèi)容與 %0100 進(jìn)行或運(yùn)算來(lái)實(shí)現(xiàn)。
說(shuō)了這么多,如果我們?cè)诰帉憛R編代碼時(shí)可以使用位操作指令,那就太好了,所以我們將在下一篇專欄中討論如何使用我們的匯編程序?qū)⑺鼈兲砑拥轿覀兊闹噶顜?kù)中。
推入和彈出(或拉出)
這些指令用于將值壓入堆棧并再次彈出(或拉出)它們。對(duì)于 6502,有 6 條與堆棧相關(guān)的指令(請(qǐng)記住,正如我們之前討論的),6502 的 8 位堆棧指針本身在上電時(shí)會(huì)自動(dòng)加載 00 美元。
TSX(將堆棧指針的值傳送到變址寄存器 X)
TXS(將變址寄存器 X 的內(nèi)容傳送到堆棧指針)
PHA(將累加器的內(nèi)容壓入堆棧)
PHP(將處理器狀態(tài)寄存器的內(nèi)容壓入)
PLA(將棧頂?shù)闹道肜奂悠鳎?br />
PLP(將棧頂?shù)闹道胩幚砥鳡顟B(tài)寄存器)
對(duì)于 HRRG,我們只有兩條指令:
PUSH(將選定的寄存器或內(nèi)存位置的內(nèi)容壓入堆棧)
POP(將堆棧頂部的值彈出到選定的寄存器或內(nèi)存位置)
HRRG 的指令適用于任何 CPU 的寄存器或內(nèi)存位置。此外,HRRG 的 MOV 指令提供(并超過(guò))6502 的 TSX 和 TXS 指令的功能。
JMP、JSR 和相關(guān)指令
JMP(無(wú)條件跳轉(zhuǎn))指令允許 CPU 跳轉(zhuǎn)到程序的另一部分。JSR 指令告訴 CPU 跳轉(zhuǎn)到子程序。JSR 通常的工作方式是用戶將任何相關(guān)信息推送到堆棧上,然后調(diào)用 JSR。反過(guò)來(lái),CPU 將程序計(jì)數(shù)器 (PC) 中的返回地址壓入堆棧,然后跳轉(zhuǎn)到子程序。
仍然在談?wù)撨@通常的工作方式,在子程序結(jié)束時(shí),使用 RTS(從子程序返回)指令將返回地址從堆棧頂部彈出到程序計(jì)數(shù)器(PC)中,并將我們返回到主程序程序。
還值得注意的是,中斷服務(wù)程序 (ISR) 的行為有點(diǎn)像子程序,因?yàn)橹袛鄷?huì)導(dǎo)致 CPU 在服務(wù)中斷之前將返回地址壓入堆棧頂部。在 ISR 結(jié)束時(shí),使用 RTI(從中斷返回)指令將返回地址從堆棧頂部彈出并返回到主程序。
6502 擁有所有這四個(gè)指令:
JMP(無(wú)條件跳轉(zhuǎn))
JSR(跳轉(zhuǎn)到子程序)
RTS(從子程序返回)
RTI(從中斷返回)
處理器還將支持一組指令,這些指令將根據(jù)狀態(tài)標(biāo)志的狀態(tài)觸發(fā)跳轉(zhuǎn)(或分支)。例如,6502 提供了 8 個(gè)這樣的指令,如下所示:
BCC(進(jìn)位標(biāo)志清除分支)
BCS(進(jìn)位標(biāo)志設(shè)置分支)
BEQ(零標(biāo)志設(shè)置分支)
BMI(負(fù)標(biāo)志設(shè)置分支)
BNE(零標(biāo)志清除分支)
BPL(負(fù)標(biāo)志清除分支)
BVC(溢出標(biāo)志清除時(shí)分支)
BVS(溢出標(biāo)志設(shè)置時(shí)分支)
與 6502 的 JMP 和 JSR 指令允許 CPU 跳轉(zhuǎn)到其 16 位地址空間內(nèi)的任何位置不同,這些分支指令使用帶符號(hào)的 8 位相對(duì)地址將控制轉(zhuǎn)移到位于向前(之后)和 128 字節(jié)內(nèi)的目標(biāo)向后(之前)分支指令的字節(jié)。程序往往會(huì)進(jìn)行大量跳轉(zhuǎn)——例如循環(huán)循環(huán)——因此在時(shí)鐘有限的日子里,使用 1 字節(jié)的分支地址而不是 2 字節(jié)的跳轉(zhuǎn)地址可能會(huì)顯著節(jié)省空間和時(shí)間速度、處理器周期和內(nèi)存位置。
在 HRRG 的情況下,我們只有兩條與跳轉(zhuǎn)相關(guān)的指令:
JMP(無(wú)條件跳轉(zhuǎn))
JSR(跳轉(zhuǎn)到子程序)
我們沒(méi)有 RTS 或 RTI 指令——我們通過(guò)簡(jiǎn)單地從堆棧頂部檢索返回地址并使用 POP 指令將其加載到程序計(jì)數(shù)器 (PC) 中來(lái)實(shí)現(xiàn)相同的效果。
問(wèn)題是我們實(shí)現(xiàn) JMP 指令的方式意味著我們可以使用它來(lái)實(shí)現(xiàn)與使用以下指令套件相同的效果:
JMP(無(wú)條件跳轉(zhuǎn))
JMPN(無(wú)條件跳轉(zhuǎn),或“從不跳轉(zhuǎn)”)*
JPN(如果為負(fù)則跳轉(zhuǎn);如果 N 標(biāo)志為 1)
JPNN(如果非負(fù)跳轉(zhuǎn);如果 N 標(biāo)志為 0)
JPZ(如果為零則跳轉(zhuǎn);如果Z 標(biāo)志為 1)
JPNZ(如果不為零則跳轉(zhuǎn);如果 Z 標(biāo)志為 0)
JPC(如果進(jìn)位則跳轉(zhuǎn);如果 C 標(biāo)志為 1)
JPNC(如果不進(jìn)位則跳轉(zhuǎn);如果 C 標(biāo)志為 0)
JPO(如果溢出則跳轉(zhuǎn);如果O 標(biāo)志為 1)
JPNO(如果沒(méi)有溢出則跳轉(zhuǎn);如果 O 標(biāo)志為 0)
JPI(如果中斷屏蔽跳轉(zhuǎn);如果 I 標(biāo)志為 1)**
JPNI(如果沒(méi)有中斷屏蔽跳轉(zhuǎn);如果 I 標(biāo)志為 0)**
JPH(如果停止則跳轉(zhuǎn);如果 H 標(biāo)志為 1)***
JPNH(如果不停止則跳轉(zhuǎn);如果 H 標(biāo)志為 0)**
注意 * JMPN(“從不跳轉(zhuǎn)”)可用于調(diào)試目的。
注意 ** 基于 I 標(biāo)志為 0 或 1 或 H 標(biāo)志為 0 的狀態(tài)的跳轉(zhuǎn)并不是特別有用,因?yàn)?a href="http://ttokpm.com/v/tag/1730/" target="_blank">程序員已經(jīng)知道這些標(biāo)志包含什么(不像 N、Z、C 和 O標(biāo)志,其值由算術(shù)和邏輯運(yùn)算的結(jié)果確定)。然而,它們是通過(guò)實(shí)現(xiàn) HRRG 的 JMP 指令的方式實(shí)現(xiàn)的。
注意 *** JPH(如果 H 標(biāo)志為 1 則跳轉(zhuǎn))完全沒(méi)有意義,這是因?yàn)橐坏┏绦驅(qū)⒋藰?biāo)志設(shè)置為 1,CPU 就會(huì)停止操作,并且只能通過(guò)觸發(fā)中斷來(lái)重置標(biāo)志(假設(shè)中斷屏蔽標(biāo)志設(shè)置為 1) 或通過(guò)重置機(jī)器,所以這里包含這條指令只是為了完整起見。
在大多數(shù)處理器的情況下,JSR(跳轉(zhuǎn)到子程序)指令的行為方式類似于 JMP(無(wú)條件跳轉(zhuǎn))指令。也就是說(shuō),沒(méi)有任何與 JPN、JPNN 等等效的 JSR。但是,由于 HRRG 的指令架構(gòu),我們可以使用 JSR 來(lái)實(shí)現(xiàn)與使用以下指令相同的效果:
JSR(無(wú)條件 JSR)
JSRN(無(wú)條件 JSR)*
JSN(如果為負(fù),則為 JSR;如果 N 標(biāo)志為 1)
JSNN(如果非負(fù),則為 JSR;如果 N 標(biāo)志為 0)
JSZ(如果為零,則為 JSR;如果 Z 標(biāo)志為 1)
JSNZ(如果不為零,則 JSR;如果 Z 標(biāo)志為 0)
JSC(如果進(jìn)位,則 JSR;如果 C 標(biāo)志為 1)
JSNC(如果不進(jìn)位,則 JSR;如果 C 標(biāo)志為 0)
JSO(如果溢出,則 JSR;如果 O 標(biāo)志為 1)
JSNO(如果沒(méi)有溢出,則 JSR;如果 O 標(biāo)志為 0)
JSI(如果中斷掩碼,則 JSR;如果 I 標(biāo)志為 1)**
JSNI(如果不是中斷掩碼,則 JSR;如果 I 標(biāo)志為 0)**
JSH(如果暫停,則 JSR;如果H 標(biāo)志為 1)***
JSNH(如果不停止,則 JSR;如果 H 標(biāo)志為 0)**
注意 *、** 和 ***;與上面討論的各種跳轉(zhuǎn)指令相同的警告適用。
即將推出……
呸!這比我預(yù)期的要花費(fèi)更多的工作,但我希望它能提供一些見解,讓我們了解我們選擇指令形成我們的極簡(jiǎn)集的方式、我們的指令與其他機(jī)器的比較,以及小騙子的使用方式。
在我的下一個(gè) HRRG 專欄中,我們將開始研究 HRRG 的匯編語(yǔ)言,包括我們?nèi)绾问褂脜R編器來(lái)實(shí)現(xiàn)不在我們核心集中的指令。此外,我們將討論與所有這一切的歷史方面有關(guān)的一些方面,例如第一個(gè)匯編程序是如何產(chǎn)生的。在此之前,我一如既往地期待您的評(píng)論、問(wèn)題和建議。
審核編輯 黃昊宇
評(píng)論
查看更多