啥是LC-3?
LC-3是一種簡單(可能?)的十六位機器語言,它具有沒什麼卵用且可能使您挂科的作用。該語言自發明以來飽受歡迎,它受歡迎就展現在它受歡迎個錘子的歡迎,内網外網啥資料找不到它受歡迎它受了個蔡徐坤的歡迎(全惱)。
不知道為啥奧大的計組要我們學這種冷門彙編(可能是因為好上手?希望他們是這麼想的罷…)…感覺相關的資源都很少,不會的地方也找不到人問,學起來太痛苦了。思前想後,這門彙編内容上其實真的不難,覺得要是後來人學起這個因為資源缺乏再遭罪實在不值得,故撰此文,希望能幫大家省去一些被知識的海洋倒灌的時間和精力。
注:本文假設您已經具有基本的計算機組成原理的知識基礎,即了解基本的二進制運算、機器語言、寄存器、記憶體尋址的常識。
二注:本文主要是給小白看的,講得可能特别啰嗦(明明就是因為我這人本來就比較啰嗦x )
この分割線だ
LC-3的基本指令結構和文法
LC-3是儲存在記憶體中的指令集合,其由十六位二進制數組成,按照記憶體位址的順序運作,通過讀寫寄存器并将值存入記憶體的方式運作。LC-3假設有從R0到R7的8個可調用的寄存器。
所有LC-3指令都符合 前4位為操作碼,後12位為操作數的結構。對于不同的操作碼的操作,後12位的操作數的具體結構不同。
一行LC-3指令大概長這樣:
操作碼 操作數
0000 000000000000
如果想在這行執行不同的指令,就需要在這行儲存不同的操作碼。
比如,假如我們要在這一行LC-3機器碼中,對寄存器R1中的數+1。
我們首先找到加法操作的文法:

ADD的操作碼是0001。當LC-3計算機發現這行代碼由0001打頭時,就會把後面的部分當作ADD操作的操作數。
Dst指儲存加法運算結果的寄存器。
Src1指儲存運算加法的一個加數的寄存器。
Imm5指要加的值
是以,我們想要的指令就為:
其等價于
R1 = R1 + 1;
0001告訴計算機我們進行的是加法運算(即格式為「Dst = Src1 + Imm5;」的運算),而不是别的。
001指計算的值要儲存在R1寄存器中,隻有被指定的寄存器才會發生改變。也就是說如果這裡指定的是010(R2寄存器),那麼經管你取出的是R1的值進行的運算,R1也不會發生改變。
就好比:
變的是R2,R1是不變的。(我是不是講太細了x)
第二個001指取出R1中的值作為加數。
1指後面的加數為常量,如果這裡為0,後面的加數就不是一個二進制常量,而會被當成一個寄存器了。
00001指加數常量。
加數有兩種形式
隻是其中一種,還有一種為
機器語言的文法格式為
可以看見,二者的主要差别在于從右數的第五位數。如果計算機讀到這行指令由0001開頭,就會再讀右數第五位數,如果為1則把最後五位數作為常數,如果為0則把最後三位數作為寄存器。
例:
可表述為LC-3指令:
看到這這行應該用不着多解釋了罷~
LC-3的主要指令
LC-3有着豐富(個錘子 )且強大(個屁 )的指令集。
主要包括:
操作指令:ADD, AND, NOT
資料遷移指令:LD, LDI, ST, STI, STR, LDR, LEA
程式控制指令:BR, JMP, RTI, TRAP, JSR/JSRR
操作指令
ADD
AND
對Src1寄存器中的每一位與Src2或一個常數中對應的每一位進行二進制 和操作,并存入Dst寄存器。
NOT
對Src1寄存器中的每一位進行二進制非操作,并存入Dst寄存器。
資料遷移指令
LD
将記憶體中的内容存入Dst寄存器。PCoffset9指PC偏移量。
PC就是現在的指令所在的記憶體位址,offset指偏移量,⑨指笨蛋 ,9指占用9位二進制數。
意思就是把PC + offset9那個位置的代碼放到指定的Dst寄存器裡頭。
比如,假如我們現在的代碼在的位址是3000(PC = 3000),
這行代碼就意味着 把位址為3015(3000 + 15)處的内容存進R2中。
LDI(花裡胡哨的)
LDI比LD複雜一點。它要多套一個娃。
LD是直接找到PC+offset的内容,然後指把這個内容搬進Dst。LDI要多一步,它先找到PC+offset,然後把PC+offset的值作為位址,再尋一遍址,然後把這個位址的内容存進Dst。(我就感覺到繞)
比如,還是用前面的例子,我們把LD簡單改成LDI。
這行代碼就意味着 把位址為3015(3000 + 15)處的内容作為位址 把這個位址的内容 存進R2中。
假如3015的内容是1500,那麼R2的值就會變成位址為1500的儲存器的值。
ST
ST是LD的逆操作,它将寄存器Src中的值存入PCoffset中的記憶體空間。
LD是把記憶體中的内容拿進寄存器,ST反過來,把寄存器的内容拿進記憶體。
STI
同理,STI是LDI的逆操作,把寄存器的指取出來,放進PCoffset的位址的内容指定的位址裡去。
LDR(更加花裡胡哨的)
Base其實就是一個寄存器。LDR要做的就是把base寄存器中的内容取出來作為位址,找到這個位址後,給它加上offset偏移值,然後把這個位址中的内容存進Dst寄存器。
比如,假如R2中的值為1919,位址為1926的記憶體空間中存的值為1145,
這串代碼指的就是把Base中的值(1919)取出來,加上7(變成1926),然後我們以之為位址,找到1926,并把裡面的值存入Dst(R1)。然後R1就變成了1145了。
STR
我覺得任何一隻貓咪都能輕而易舉地猜到這肯定是LDR是逆操作。
前面的步驟不變,把最後一步反過來(記憶體中的值存進寄存器變成寄存器中的值存進記憶體)即可。
LEA(好!很直接!)
LEA沒有任何尋址,它僅僅隻是把PC+offset的位址的值存進寄存器Dst。非常得友好,非常得好了解。事鑒語句。
程式控制指令
BR
這個屑指令tlld我課件沒看懂百度谷歌查了好長時間都沒找到相關的起碼折騰了我兩三個小時氣死我學tnd屑指令wdnmd
(冷靜下來)BR指令是LC-3中最基礎的跳轉指令,作用類似于進階語言中的while、 for等循環語句(也可以當if用),但是了解起來不那麼容易。
這裡推薦大家可以移步哔哩哔哩大學參考一下這個灣灣做的視訊:
https://www.bilibili.com/video/BV1uK411J7qK?p=16 屬實救我性命
BR語句的基本格式如下:
nzp類似于進階語言中的判斷表達式(就是C、java裡的while語句中圓括号裡的東西),n是negative的意思,意味着判斷上一個操作的寄存器的值是否小于零,z是zero的意思,意味着判斷上一個操作的寄存器的值是否等于零,p是positive的意思,意味着判斷上一個操作的寄存器的值是否大于零。
什麼?你問我計算機怎麼判斷上一個操作過的寄存器的正負值?專門取出來判斷一遍嗎?我本來也納悶這個,後來我才知道LC-3的計算機裡頭專門有三個bit存上一個寄存器的值(這個我查了老半天(怨))。
LC-3的計算機中每進行一次寄存器操作,LC-3就會記錄這個寄存器的正負值,并存在那三個bit中。比如我把-1指派給R1,LC-3中記錄nzp的值的那三個bit就會變成100(n為1,指這個值是負數)(不可能出現110這樣的,沒有數既是負數又是0)。
而語句中的nzp則用于判斷LC-3中的記錄nzp的三個bit中的值是否符合語句中的nzp。
比如,語句中的nzp為010,這的含義就是「假如上一個被操作過的寄存器的值為0,我就把PC (現在的執行的指令的位址)設為PC+offset,否則繼續按正常順序執行指令」。
可以了解為while (Rx(上一個被操作的寄存器) == 0) {}這樣的語句。
如果語句中的nzp為110,就可以了解為while (Rx(上一個被操作的寄存器) <= 0) {}這樣的語句。
如果為111,則相當于必然跳轉。
總結:BR語句的含義就是,如果上一個操作過的寄存器的值符合指令中的nzp的條件,則對現有的PC進行跳轉,否則繼續執行下一個指令。
一般BR在使用時有兩種用法。
一個是循環的實作。
在BR前面放一個寄存器運算指令。比如
R1 = R1 - 1;
這樣的。然後在一開始設定R1位某個特定正數值,把br語句的nzp設定為001(若R1>0)或者011(若R1>=0),則将PC跳轉至之前的某一個位置(offset為負數),也就是說重新執行一遍前面的一段指令。然後R1不斷減一,直到為零或者小于零。這就是while和for的彙編底層實作。
另一個是條件分支判斷,即if的實作。
和之前不同的地方在于嗎,如果要實作if,offset值一般設定為正數,即假如符合條件,就跳過一段指令(不執行),不符合就執行這段指令。
(如果還沒看明白可以私聊我orz,我語音+畫圖可能了解更清晰一些orz)
JMP
覺得BR用起來麻煩?學着糟心?看着頭大?來用JMP罷!你用不了上當用不了吃虧…
JMP文法很簡單,啥條件判斷妹有,說跳就跳(無條件跳轉),想跳哪就跳哪(與BR使用偏移量跳轉不同,它使用的是直接尋址)。
JMP會讀取Base寄存器中的數值作為位址,然後直接把PC置為該位址,簡單粗暴直接,事鑒語句(确信)。
RTI(這個好像叫RET,沒搞懂到底叫啥)
比JMP更加簡單粗暴,直接指定一個常數作為位址,然後把PC設為這個位址。
格式: 1100 + 十二位常數。
TRAP
t rap,是一種rap ,是trapvector的縮寫,意為陷阱矢量。
它會先把現在的PC + 1的值給R7,然後把trapvector8中的值作為PC。
我其實不是很明白有明白的可以來教我一下,…
JSR/JSRR
JSR看起來就是把PC + 1交給R7,然後PC加上常量offset偏移值。(不是很了解這是在幹啥x)
JSRR也很粗暴,也是把PC + 1交給R7,然後PC變為Base寄存器中的值。
我在想假如Base寄存器指定為R7會咋樣()。(可能會直接執行下一行罷)
碼了一上午了有點累,也權當給自己複習複習。僞代碼和網絡程式設計的内容咱自己也有一些不明白,是以放到後面寫罷orz,到時候整點例題來給大家看看
大家如果有什麼問題或者建議可以加咱的QQ306168645來交流。來閑聊也星233333,咱超話痨的,雖說咱未必有時間orz
大家學習順利愉快w