版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡介
1、<p><b> C語言課程設(shè)計(jì)報(bào)告</b></p><p> 題目:模擬器和匯編程序的設(shè)計(jì)</p><p> 專 業(yè):計(jì)算機(jī)科學(xué)與技術(shù)</p><p><b> 班 級:</b></p><p><b> 學(xué) 號:</b>&
2、lt;/p><p><b> 姓 名:</b></p><p><b> 成 績:</b></p><p><b> 指導(dǎo)教師: </b></p><p> 完成日期: 2012年 10 月 15 日</p><p><
3、b> 目 錄</b></p><p> 一、系統(tǒng)需求分析1</p><p><b> 二、總體設(shè)計(jì)6</b></p><p> 三、數(shù)據(jù)結(jié)構(gòu)設(shè)計(jì)7</p><p><b> 四、詳細(xì)設(shè)計(jì)9</b></p><p><b> 五
4、、系統(tǒng)實(shí)現(xiàn)13</b></p><p> 六、運(yùn)行測試與結(jié)果分析42</p><p><b> 七、總結(jié)44</b></p><p><b> 八、參考文獻(xiàn)45</b></p><p> 九、指導(dǎo)教師評語46</p><p><b>
5、 一、系統(tǒng)需求分析</b></p><p> Simulator and Assembler</p><p> 1. 用C語言編制匯編程序,將此簡單計(jì)算機(jī)的匯編源程序翻譯成目標(biāo)代碼,即機(jī)器碼。為了測試所編制匯編程序的正確性,需用以上介紹的指令集編寫兩個(gè)匯編源程序,匯編源程序的功能要求為:</p><p> 求1+2+3+…+100,并輸出運(yùn)算結(jié)果。
6、</p><p> ② 求將” Simulator and Assembler”拷貝復(fù)制到新串并輸出運(yùn)算結(jié)果。</p><p><b> 串并輸出運(yùn)算結(jié)果。</b></p><p> 其中,32條指令以及偽指令和它們的功能如下:</p><p> (1) 停機(jī)指令:HLT</p><p>
7、 功能:終止程序運(yùn)行。</p><p> (2) 無條件轉(zhuǎn)移指令:JMP label</p><p> 功能:將控制轉(zhuǎn)移至標(biāo)號label處,執(zhí)行標(biāo)號label后的指令。</p><p> (3) 比較運(yùn)算轉(zhuǎn)移指令:CJMP label</p><p> 功能:如果程序狀態(tài)字中比較標(biāo)志位c的值為1(即關(guān)系運(yùn)算的結(jié)
8、果為真),則將控制轉(zhuǎn)移至標(biāo)號label處,執(zhí)行標(biāo)號label后的指令;否則,順序往下執(zhí)行。</p><p> (4) 溢出轉(zhuǎn)移指令:OJMP</p><p> 功能:如果程序狀態(tài)字中比較標(biāo)志位o的值為1(即算術(shù)運(yùn)算的結(jié)果發(fā)生溢出),則將控制轉(zhuǎn)移至標(biāo)號label處,執(zhí)行標(biāo)號label后的指令;否則,順序往下執(zhí)行。</p><p> (5) 調(diào)用子程序指令:CAL
9、L label</p><p> 功能:將通用寄存器A~G、程序狀態(tài)字PSW、程序計(jì)數(shù)器PC中的值保存到ES,然后調(diào)用以標(biāo)號label開始的子程序,將控制轉(zhuǎn)移至標(biāo)號label處,執(zhí)行標(biāo)號label后的指令。</p><p> (6) 子程序返回指令:RET</p><p> 功能:將ES中保存的通用寄存器A~Z、程序狀態(tài)字PSW和程序字?jǐn)?shù)器PC的
10、值恢復(fù),控制轉(zhuǎn)移到子程序被調(diào)用的地方,執(zhí)行調(diào)用指令的下一條指令。</p><p> (7) 入棧指令:PUSH reg0</p><p> 功能:將通用寄存器reg0的值壓入堆棧SS,reg0可以是A~G和Z八個(gè)通用寄存器之一。</p><p> (8) 出棧指令:POP reg0</p><p> 功能:從堆
11、棧SS中將數(shù)據(jù)出棧到寄存器reg0,reg0可以是A~G七個(gè)通用寄存器之一,但不能是通用寄存器Z。</p><p> (9) 取字節(jié)數(shù)據(jù)指令:LOADB reg0 symbol</p><p> 功能:從字節(jié)數(shù)據(jù)或字節(jié)數(shù)據(jù)塊symbol中取一個(gè)字節(jié)的數(shù)據(jù)存入寄存器reg0,所取的字節(jié)數(shù)據(jù)在數(shù)據(jù)塊symbol中的位置由寄存器G的值決定。用C的語法可將此指令的功能描述
12、為:</p><p> reg0 = symbol[G]</p><p> 例如,假設(shè)用偽指令定義了以下字節(jié)數(shù)據(jù)塊num:</p><p> BYTE num[10] = {5,3,2,8,6,9,1,7,4,0}</p><p> 如果要將字節(jié)數(shù)據(jù)塊num中第5個(gè)單元的值(即下標(biāo)為4的元素)取到寄存器C,指令如下:<
13、/p><p> LOADI G 5</p><p> LOADB C num</p><p> 后面的指令LOADW、STOREB和STOREW在操作上與此指令類似。</p><p> (10) 取雙字節(jié)數(shù)據(jù)指令:LOADW reg0 symbol</p>
14、<p> 功能:從雙字節(jié)數(shù)據(jù)或雙字節(jié)數(shù)據(jù)塊symbol中取一個(gè)雙字節(jié)的數(shù)據(jù)存入寄存器reg0,所取的雙字節(jié)數(shù)據(jù)在數(shù)據(jù)塊symbol中的位置由寄存器G的值決定。</p><p> (11) 存字節(jié)數(shù)據(jù)指令:STOREB reg0 symbol</p><p> 功能:將寄存器reg0的值存入字節(jié)數(shù)據(jù)或字節(jié)數(shù)據(jù)塊symbol中的某個(gè)單元,存入單元的位置
15、由寄存器G的值決定。用C的語法可將此指令的功能描述為:</p><p> symbol[G] = reg0</p><p> (12) 存雙字節(jié)數(shù)據(jù)指令:STOREW reg0 symbol</p><p> 功能:將寄存器reg0的值存入雙字節(jié)數(shù)據(jù)或雙字節(jié)數(shù)據(jù)塊symbol中的某個(gè)單元,存入單元的位置由寄存器G的值決定。</p&g
16、t;<p> (13) 取立即數(shù)指令:LOADI reg0 immediate</p><p> 功能:將指令中的立即數(shù)immediate存入寄存器reg0。立即數(shù)被當(dāng)作16位有符號數(shù),超出16位的高位部分被截掉。例如:</p><p> LOADI B 65535</p><p> 寄存器
17、B的值為-1。</p><p> LOADI B 65537</p><p><b> 寄存器B的值為1。</b></p><p> (14) 空操作指令:NOP</p><p> 功能:不執(zhí)行任何操作,但耗用一個(gè)指令執(zhí)行周期。</p><p> (15)
18、控制臺輸入指令:IN reg0 0</p><p> 功能:從輸入端口(即鍵盤輸入緩沖區(qū))取一個(gè)字符數(shù)據(jù),存入寄存器reg0。</p><p> (16) 控制臺輸出指令:OUT reg0 15</p><p> 功能:將寄存器reg0的低字節(jié)作為字符數(shù)據(jù)輸出到輸出端口(即顯示器)。</p>&
19、lt;p> (17) 加運(yùn)算指令:ADD reg0 reg1 reg2</p><p> 功能:將寄存器reg1的值加上reg2的值,結(jié)果存入寄存器reg0。如果結(jié)果超過16位有符號數(shù)的表示范圍,將發(fā)生溢出,使程序狀態(tài)字的溢出標(biāo)志位o置為1;如果未發(fā)生溢出,則使程序狀態(tài)字的溢出標(biāo)志位o置為0。</p><p> (18) 加立即數(shù)指令:AD
20、DI reg0 immediate</p><p> 功能:將寄存器reg0的值加上立即數(shù)immediate,結(jié)果仍存入寄存器reg0。如果結(jié)果超過16位有符號數(shù)的表示范圍,將發(fā)生溢出,使程序狀態(tài)字的溢出標(biāo)志位o置為1;如果未發(fā)生溢出,則使程序狀態(tài)字的溢出標(biāo)志位o置為0。</p><p> (19) 減運(yùn)算指令:SUB reg0 reg
21、1 reg2</p><p> 功能:將寄存器reg1的值減去reg2的值,結(jié)果存入寄存器reg0。如果結(jié)果超過16位有符號數(shù)的表示范圍,將發(fā)生溢出,使程序狀態(tài)字的溢出標(biāo)志位o置為1;如果未發(fā)生溢出,則使程序狀態(tài)字的溢出標(biāo)志位o置為0。</p><p> (20) 減立即數(shù)指令:SUBI reg0 immediate</p><p
22、> 功能:將寄存器reg0的值減去立即數(shù)immediate,結(jié)果仍存入寄存器reg0。如果結(jié)果超過16位有符號數(shù)的表示范圍,將發(fā)生溢出,使程序狀態(tài)字的溢出標(biāo)志位o置為1;如果未發(fā)生溢出,則使程序狀態(tài)字的溢出標(biāo)志位o置為0。</p><p> (21) 乘運(yùn)算指令:MUL reg0 reg1 reg2</p><p> 功能:將寄存器reg1
23、的值乘以reg2的值,結(jié)果存入寄存器reg0。如果結(jié)果超過16位有符號數(shù)的表示范圍,將發(fā)生溢出,使程序狀態(tài)字的溢出標(biāo)志位o置為1;如果未發(fā)生溢出,則使程序狀態(tài)字的溢出標(biāo)志位o置為0。</p><p> (22) 除運(yùn)算指令:DIV reg0 reg1 reg2</p><p> 功能:將寄存器reg1的值除以reg2的值,結(jié)果存入寄存器reg0,這
24、里進(jìn)行的是整數(shù)除運(yùn)算。如果寄存器reg2的值為零,將發(fā)生除零錯(cuò)。</p><p> (23) 按位與運(yùn)算指令:AND reg0 reg1 reg2</p><p> 功能:將寄存器reg1的值與reg2的值進(jìn)行按位與運(yùn)算,結(jié)果存入寄存器reg0。</p><p> (24) 按位或運(yùn)算指令:OR reg0
25、 reg1 reg2</p><p> 功能:將寄存器reg1的值與reg2的值進(jìn)行按位或運(yùn)算,結(jié)果存入寄存器reg0。</p><p> (25) 按位異或運(yùn)算指令:NOR reg0 reg1 reg2</p><p> 功能:將寄存器reg1的值與reg2的值進(jìn)行按位異或(按位加)運(yùn)算,結(jié)果存入寄存
26、器reg0。</p><p> (26) 按位取反運(yùn)算指令:NOTB reg0 reg1</p><p> 功能:將寄存器reg1的值按位取反后,結(jié)果存入寄存器reg0。</p><p> (27) 算術(shù)左移運(yùn)算指令:SAL reg0 reg1 reg2</p><p>
27、 功能:將寄存器reg1的值算術(shù)左移reg2位,結(jié)果存入寄存器reg0。在進(jìn)行算術(shù)左移時(shí),低位空位用0填充。</p><p> (28) 算術(shù)右移運(yùn)算指令:SAR reg0 reg1 reg2</p><p> 功能:將寄存器reg1的值算術(shù)右移reg2位,結(jié)果存入寄存器reg0。在進(jìn)行算術(shù)右移時(shí),高位空位用符號位填充。</p>&l
28、t;p> (29) 相等關(guān)系運(yùn)算指令:EQU reg0 reg1</p><p> 功能:將兩個(gè)寄存器reg0和reg1的值進(jìn)行相等比較關(guān)系運(yùn)算:reg0 == reg1,關(guān)系運(yùn)算的結(jié)果為邏輯真或邏輯假,存入程序狀態(tài)字中的比較標(biāo)志位c。</p><p> (30) 小于關(guān)系運(yùn)算指令:LT reg0 reg1</p>
29、<p> 功能:將兩個(gè)寄存器reg0和reg1的值進(jìn)行小于關(guān)系運(yùn)算:reg0 < reg1,關(guān)系運(yùn)算的結(jié)果為邏輯真或邏輯假,存入程序狀態(tài)字中的比較標(biāo)志位c。</p><p> (31) 小于等于關(guān)系運(yùn)算指令:LTE reg0 reg1</p><p> 功能:將兩個(gè)寄存器reg0和reg1的值進(jìn)行小于等于關(guān)系運(yùn)算:reg0 <= r
30、eg1,關(guān)系運(yùn)算的結(jié)果為邏輯真或邏輯假,存入程序狀態(tài)字中的比較標(biāo)志位c。</p><p> (32) 比較標(biāo)志位取反指令:NOTC</p><p> 功能:將程序狀態(tài)字中的比較標(biāo)志位c求反,即將邏輯真變?yōu)檫壿嫾伲瑢⑦壿嫾僮優(yōu)檫壿嬚妗?lt;/p><p> (33) 字節(jié)數(shù)據(jù)定義偽指令:BYTE symbol[n] = {...} 藍(lán)色字體部分為可選項(xiàng)
31、</p><p> 或:BYTE symbol[n] = "..." 藍(lán)色字體部分為可選項(xiàng)</p><p> 功能:定義長度為1字節(jié)的字節(jié)型數(shù)據(jù)或數(shù)據(jù)塊,字節(jié)型數(shù)據(jù)塊類似于C的字符數(shù)組。</p><p> (34) 字?jǐn)?shù)據(jù)定義偽指令:WORD symbol[n] = {...} 藍(lán)色字體部分為可選項(xiàng)</p&
32、gt;<p> 功能:定義長度為2字節(jié)的雙字節(jié)型數(shù)據(jù)或數(shù)據(jù)塊,雙字節(jié)型數(shù)據(jù)塊類似于C的整型數(shù)組(16位系統(tǒng))。</p><p> 用C語言編制一個(gè)模擬器,能夠模擬此簡單計(jì)算機(jī)執(zhí)行匯編程序生成的目標(biāo)代碼,得到運(yùn)行結(jié)果。</p><p> 注:編寫好編譯程序和模擬器后,再用八皇后程序檢驗(yàn)。</p><p><b> 二、總體設(shè)計(jì)</
33、b></p><p> 模擬器和匯編程序設(shè)計(jì)</p><p><b> 編譯程序</b></p><p> 編譯程序從匯編語言源文件中第一行開始,每次取一條指令,對其進(jìn)行解析并翻譯成十六進(jìn)制的目標(biāo)代碼,存入目標(biāo)文件,直到源文件結(jié)束。</p><p> 用循環(huán)反復(fù)處理從源文件輸入的每一行指令,直到遇到文件尾時(shí)
34、終止循環(huán);用函數(shù)fgets從源文件讀入一行字符串,存入字符數(shù)組a_line。</p><p> 對注釋的處理:用函數(shù)strchr查找a_line中字符 '#' 首次出現(xiàn)的位置,如果找到則用空字符'\0' 來替換。用此方法去掉指令尾部的注釋。</p><p> 對標(biāo)號的處理:建立一個(gè)鏈表來存儲標(biāo)號的位置,名稱等信息,第一遍掃描源程序時(shí),用函數(shù)strchr查
35、找a_line中字符 ':' 出現(xiàn)的位置,將標(biāo)號的名稱和位置存入鏈表中,在翻譯目標(biāo)代碼時(shí),再計(jì)算標(biāo)號的偏移量。</p><p> 對偽指令的處理:建立一個(gè)存儲偽指令定義的標(biāo)識符的類型,名稱,長度,數(shù)據(jù)等信息的鏈表,第一遍掃描源程序時(shí),將偽指令的信息存入鏈表中。翻譯目標(biāo)代碼時(shí),將偽指令定義的變量值放在所有目標(biāo)代碼的后面。</p><p><b> 模擬器<
36、/b></p><p> 模擬器對該簡單計(jì)算機(jī)的處理器、內(nèi)存和終端設(shè)備進(jìn)行模擬。當(dāng)模擬器運(yùn)行時(shí),首先將經(jīng)匯編程序匯編后的目標(biāo)程序讀入到內(nèi)存,然后模擬目標(biāo)程序的運(yùn)行,直到執(zhí)行HLT指令時(shí)終止。</p><p> 用一個(gè)無符號字符類型的數(shù)組來模擬內(nèi)存;目標(biāo)文件中每行存放一條十六進(jìn)制的指令代碼,依次將每行指令代碼讀入到模擬內(nèi)存中;8個(gè)通用寄存器A~G和Z用unsigned short數(shù)
37、組來模擬;處理器可用“取指——解碼——執(zhí)行”循環(huán)來模擬。</p><p><b> 三、數(shù)據(jù)結(jié)構(gòu)設(shè)計(jì)</b></p><p><b> 編譯程序</b></p><p> 編譯程序中,用先進(jìn)先出鏈表來存放標(biāo)號和偽指令的有關(guān)數(shù)據(jù),具體如下圖:</p><p> 存放偽指令定義的標(biāo)識符的鏈表大致
38、如上</p><p> 當(dāng)掃描匯編源程序時(shí),處理標(biāo)號和偽指令,此時(shí)建立鏈表并存儲信息。在調(diào)用計(jì)算標(biāo)號的偏移量和輸出偽指令定義的變量值時(shí),再遍歷鏈表。</p><p><b> 模擬器</b></p><p> 模擬器中,內(nèi)存的結(jié)構(gòu)大致如下</p><p> 其中,CS是代碼段,DS是數(shù)據(jù)段,SS是堆棧段,ES是附
39、加段,Port是兩個(gè)終端設(shè)備控制臺。代碼段用無符號長整型數(shù)組模擬,數(shù)據(jù)段用無符號字符型數(shù)組模擬,堆棧段用短整型數(shù)組模擬,而附加段用存放若干個(gè)結(jié)構(gòu)體指針的數(shù)組來模擬,這里的結(jié)構(gòu)體中存放了指令計(jì)數(shù)器PC、程序狀態(tài)字PSW和通用寄存器。</p><p> 加載目標(biāo)代碼時(shí),指令計(jì)數(shù)器PC指向內(nèi)存的頂端,依次將指令加載到模擬內(nèi)存。加載完后,將PC指向堆棧段SS,然后將偽指令定義的變量存入數(shù)據(jù)段,數(shù)據(jù)段DS緊接著數(shù)據(jù)段CS
40、,SS緊挨著DS,而將ES放到內(nèi)存的底部。因此SS和ES進(jìn)出的方向是相反的。</p><p> 下面簡要說一下堆棧段和附加段的用法:</p><p> 在CALL指令調(diào)用并執(zhí)行子程序,控制將轉(zhuǎn)移到子程序,子程序的地址由標(biāo)號給出。如果調(diào)用子程序前需要向子程序傳遞參數(shù)(類似于函數(shù)的參數(shù)),可用PUSH指令將參數(shù)壓入堆棧,子程序中用POP指令取出參數(shù),注意堆棧是先進(jìn)后出。參數(shù)是通過堆棧段傳遞
41、的。更重要的是,在將控制轉(zhuǎn)移到子程序前,CALL指令要將相關(guān)寄存器(主要是指令計(jì)數(shù)器PC、程序狀態(tài)字PSW和通用寄存器)的內(nèi)容保存起來,因?yàn)樽映绦蛞惨眠@些寄存器存放指令或數(shù)據(jù)。這些寄存器的值保存在附加段中,附加段的使用類似于堆棧段,但他們存放數(shù)據(jù)的方向不一樣,堆棧段數(shù)據(jù)進(jìn)棧時(shí),棧頂向高地址方向增加,出棧則向低地址方向減小;附加段棧頂?shù)淖兓门c堆棧段的棧頂相反,堆棧段SS和附加段ES共用一塊內(nèi)存區(qū),這樣設(shè)計(jì)的理由是提高內(nèi)存的利用率。當(dāng)
42、子程序執(zhí)行到RET指令時(shí),控制要返回到先前CALL指令的下一條指令接著執(zhí)行,從附加段中把保存的相關(guān)寄存器的值恢復(fù)到原寄存器即可。</p><p><b> 詳細(xì)設(shè)計(jì)</b></p><p><b> 1. 編譯程序</b></p><p> 編譯程序從匯編語言源文件中第一行開始,每次取一條指令,對其進(jìn)行解析并翻譯成十
43、六進(jìn)制的目標(biāo)代碼,存入目標(biāo)文件,直到源文件結(jié)束。</p><p> 用循環(huán)反復(fù)處理從源文件輸入的每一行指令,直到遇到文件尾時(shí)終止循環(huán);用函數(shù)fgets從源文件讀入一行字符串,存入字符數(shù)組a_line。</p><p> 用函數(shù)sscanf從數(shù)組a_line中輸入一個(gè)字符串到字符數(shù)組op_sym并將函數(shù)返回值賦給n。如果n為0,哪么數(shù)組a_line中存放的是空行或注釋行,直接取下一行再接
44、著進(jìn)行處理。如果n不為0,那么讀入數(shù)組op_sym中的字符串就是該指令的助記符,由此可知該指令的格式。</p><p> 接下來再次用函數(shù)sscanf從數(shù)組a_line中輸入字符串到以下4個(gè)字符數(shù)組op_sym,reg0,reg1和reg2,分別判斷reg0,reg1和reg2中的字符串,并依次給對應(yīng)的整型變量arg0,arg1和arg2賦值。</p><p> 在此之前,用宏指令將每
45、個(gè)指定助記符都定義成符號常量,以表示指令助記符對應(yīng)的指令操作碼;同樣,將各條指令轉(zhuǎn)換成目標(biāo)代碼的算法定義成帶參的宏。</p><p> 再用函數(shù)fgets從源文件讀入下一行字符串,進(jìn)行下一輪循環(huán)處理。</p><p> 下面是編譯程序的流程圖:</p><p><b> 2. 模擬器</b></p><p> 由
46、于每條指令的長度是4個(gè)字節(jié),所以將程序計(jì)數(shù)器PC定義成無符號長整型指針,這樣,一次可以取到一條完整的指令,同時(shí)程序計(jì)數(shù)器的值加1就可以指向下一條指令。</p><p> 在將指令代碼讀到模擬內(nèi)存時(shí),先用fscanf函數(shù)從目標(biāo)文件中讀取一條指令代碼到一個(gè)unsigned long類型的臨時(shí)變量,然后用memcpy函數(shù)將該臨時(shí)變量的內(nèi)容復(fù)制到模擬內(nèi)存中。</p><p> 處理器在執(zhí)行時(shí),
47、從程序計(jì)數(shù)器PC指示的內(nèi)存單元將指令載入到指令寄存器IR,然后將PC的值增加1,使其指向下一條指令,為下一輪循環(huán)做準(zhǔn)備。接下來對指令進(jìn)行解碼。另外,將寄存器編號、立即數(shù)、數(shù)據(jù)在內(nèi)存中的地址定義成宏。其中,指令操作碼opcode可通過按位右移得到:OPCODE = (IR >> 27) & 0x0F;通用寄存器用unsigned short數(shù)組來模擬;每條指令的功能用一個(gè)無參整型函數(shù)來實(shí)現(xiàn),再定義一個(gè)函數(shù)指針數(shù)組ops
48、,將32個(gè)函數(shù)的入口地址保存到數(shù)組ops中,數(shù)組下標(biāo)與函數(shù)所對應(yīng)指令操作碼一致,這樣,從指令中解碼得到指令操作碼后,就可以用如下表達(dá)式調(diào)用指令功能的實(shí)現(xiàn)函數(shù),模擬指令的執(zhí)行。</p><p> (*ops[OPCODE])();</p><p> 接下來進(jìn)行下一輪循環(huán),直到執(zhí)行函數(shù)HLT退出循環(huán)。</p><p> 下面是模擬器程序的流程圖:</p>
49、;<p><b> 五、系統(tǒng)實(shí)現(xiàn)</b></p><p><b> 兩個(gè)匯編程序源碼:</b></p><p><b> 累加:</b></p><p><b> #1加到100</b></p><p> LOADIA100
50、# 循環(huán)的上界設(shè)為100</p><p> LOADIB1# 將循環(huán)次數(shù)存入寄存器B中</p><p> LOADIC0# 將和數(shù)存入寄存器C中</p><p> LOADID10# 用于轉(zhuǎn)換時(shí)的除數(shù)</p><p> LOADIE1000# 將和數(shù)轉(zhuǎn)換成字符的除數(shù)</p><p&g
51、t; LOADIF0# 用于提取個(gè)位,十位等的數(shù)字</p><p> LOADIG0# 用于轉(zhuǎn)換時(shí)的減數(shù)</p><p> loop:ADDCCB# 計(jì)算D = C + B</p><p> ADDIB1# 將B的值增加1</p><p> LTEBA# B <= A?</p&g
52、t;<p> CJMPloop# 若B <= A 為真,則跳到loop處</p><p> loop2: DIVFCE# F = C / E</p><p> ADDIF48# 將數(shù)字轉(zhuǎn)化為數(shù)字字符</p><p> OUTF15# 輸出F</p><p> SUBIF48
53、# 將數(shù)字字符轉(zhuǎn)化為數(shù)字</p><p> MULGFE# G = F * E</p><p> SUBCCG# C = C - G</p><p> DIVEED# E = E / D</p><p> LOADIA0# A = A - 100</p><p> LTEE
54、A# E <= 0?</p><p> NOTC# 取反,即E > 0</p><p> CJMPloop2# 若E > 0 為真,則跳到loop2處</p><p> HLT# 結(jié)束</p><p><b> 拷貝字符串:</b></p><p
55、><b> #拷貝字符串</b></p><p> BYTEstr[24] = "Simulator and Assembler"</p><p> BYTEs[24]</p><p> LOADIA19</p><p><b> LOADIB0</b
56、></p><p><b> LOADIC0</b></p><p><b> LOADID0</b></p><p><b> LOADIE0</b></p><p> LOADIG0# 將數(shù)組下限設(shè)為0</p><p&g
57、t;<b> SUBIG4</b></p><p> loop: LOADBBstr</p><p> STOREBBs</p><p><b> LOADBCs</b></p><p><b> ADDDGE</b></p>
58、<p> ADDID48</p><p><b> OUTC15</b></p><p><b> ADDIG1</b></p><p><b> LTGA</b></p><p><b> CJMPloop</b>
59、</p><p><b> HLT</b></p><p><b> 編譯程序源碼:</b></p><p> #include <stdio.h></p><p> #include <stdlib.h></p><p> #include
60、 <string.h></p><p> #include <ctype.h></p><p> #define MAX_LEN 150</p><p> #define INSTRS_COUNT (sizeof(g_instrs_name)/sizeof(g_instrs_name[0]))</p><p>
61、 #define INSTR_SYM {"HLT","JMP","CJMP","OJMP","CALL","RET","PUSH","POP","LOADB",\</p><p> "LOADW","ST
62、OREB","STOREW","LOADI","NOP","IN","OUT","ADD",\</p><p> "ADDI","SUB","SUBI","MUL","DIV",&qu
63、ot;AND","OR","NOR","NOTB",\</p><p> "SAL","SAR","EQU","LT","LTE","NOTC","BYTE","WORD"\</
64、p><p><b> }</b></p><p> const char *g_instrs_name[] = INSTR_SYM; /*定義存放指令記號的數(shù)組*/</p><p> const char instr_format[33] = "12222133444451667575777778778881"
65、;;</p><p> int GetInstrCode(const char *op_sym); /*由指令助記符得到指令代碼*/</p><p> unsigned long TransToCode(char *instr_line, int instr_num); /*指令的譯碼*/</p><p> int GetRegNum(ch
66、ar *instr_line, char *reg_name); /*由寄存器名對應(yīng)到代碼*/</p><p> typedef struct tab</p><p><b> {</b></p><p> int addr; /*標(biāo)號偏移量*/</p><p> ch
67、ar str[20]; /*標(biāo)號名稱*/</p><p> struct tab *next;</p><p><b> }TAB;</b></p><p> typedef struct byte_word</p><p><b> {</b></p>
68、<p> int type; /*類型*/</p><p> char name[8]; /*變量名*/</p><p> int num; /*數(shù)組長度*/</p><p> long dat[65]; /*數(shù)據(jù)*/</p><p
69、> struct byte_word *next;</p><p> }BYTE_WORD;</p><p> TAB *head1 = NULL;</p><p> BYTE_WORD *head2 = NULL;</p><p> int main(int argc, char **argv)</p><
70、;p><b> {</b></p><p> char a_line[MAX_LEN];</p><p> char op_sym[8];</p><p> int op_num;</p><p> int s = 0, k = 0, m = 0, j = 0, p = 0, q = 0;</p&g
71、t;<p> char num[5];</p><p> char dat[50][50];</p><p> unsigned long str[4];</p><p> char *pcPos;</p><p> FILE *pfIn, *pfOut;</p><p> head1 = (
72、struct tab *)malloc(sizeof(struct tab));</p><p> TAB *p1 = head1;</p><p> head2 = (struct byte_word *)malloc(sizeof(struct byte_word));</p><p> BYTE_WORD *p2 = head2, *temp, *tai
73、l = head2;</p><p><b> int n;</b></p><p> if (argc < 3) /*檢查命令行參數(shù)數(shù)目*/</p><p><b> {</b></p><p> printf("ERROR:no enough command
74、line arguments!\n");</p><p><b> return 0;</b></p><p><b> }</b></p><p> if ((pfIn = fopen(argv[1], "r")) == NULL) /*打開源代碼文件*/</p>
75、;<p><b> {</b></p><p> printf("ERROR:cannot open file %s for reading!\n", argv[1]);</p><p><b> return 0;</b></p><p><b> }</b>
76、;</p><p> if ((pfOut = fopen(argv[2], "w")) == NULL) /*打開目標(biāo)代碼文件*/</p><p><b> {</b></p><p> printf("ERROR:cannot open file %s for writing!\n",
77、 argv[2]);</p><p><b> return 0;</b></p><p><b> }</b></p><p> while (!feof(pfIn)) /*處理標(biāo)號和偽指令*/</p><p><b> {</b&g
78、t;</p><p> fgets(a_line, MAX_LEN, pfIn); /*從源文件中取出一條指令*/</p><p> if ((pcPos = strchr(a_line, '#')) != NULL)</p><p> *pcPos = '\0';</p><p> n =
79、 sscanf(a_line, "%s", op_sym); /*從指令中取指令助記符*/</p><p><b> if(n < 1)</b></p><p><b> continue;</b></p><p> if(strchr(a_line, ':') != N
80、ULL) /*處理標(biāo)號*/</p><p><b> {</b></p><p> p1->addr = s; /*記錄標(biāo)號的行數(shù)*/</p><p> sscanf(a_line, "%[^:]", p1->str
81、); /*將冒號為止的字符串存入str中*/</p><p> p1->next = (struct tab *)malloc(sizeof(struct tab));</p><p> p1 = p1->next;</p><p><b> }</b></p><p> if (
82、(strcmp("BYTE", op_sym) == 0) || (strcmp("WORD", op_sym) == 0)) /*處理變量*/</p><p><b> {</b></p><p> if(strcmp("BYTE", op_sym) == 0)</p><
83、;p> p2->type = 1;</p><p><b> else</b></p><p> p2->type = 2;</p><p> sscanf(a_line, "%*s%s", p2->name); /*存變量名*/</p><p&
84、gt; while(p2->name[k] != '\0') /*去掉字符串中方括號的部分*/</p><p><b> {</b></p><p> if(p2->name[k] == '[')</p><p> p2->name[k] = '\0&
85、#39;;</p><p><b> k++;</b></p><p><b> }</b></p><p><b> k = 0;</b></p><p> if(strchr(a_line, '[') != NULL)</p><
86、p><b> {</b></p><p> sscanf(a_line, "%*[^[][%[0-9]", num);</p><p> p2->num = atoi(num); /*將num轉(zhuǎn)化為整數(shù)*/</p><p> for(m = 0; m < p2->num; m
87、++)</p><p> p2->dat[m] = 0;</p><p><b> m = 0;</b></p><p> if(strchr(a_line, '=') != NULL)</p><p><b> {</b></p><p>
88、while ((a_line[j] != '{') && (a_line[j] != '"'))</p><p><b> j++;</b></p><p> if(a_line[j] == '"')</p><p><b> {</b&g
89、t;</p><p> while(a_line[++j] != '"')</p><p> p2->dat[m++] = a_line[j];</p><p><b> }</b></p><p><b> else</b></p><p
90、><b> {</b></p><p> while (a_line[++j] != '}')</p><p><b> {</b></p><p> if (isdigit(a_line[j])) /*如果是數(shù)字*/</p><p> dat[p][m++]
91、 = a_line[j];</p><p> else if (a_line[j] == ',')</p><p><b> {</b></p><p><b> p++;</b></p><p><b> m = 0;</b></p>&
92、lt;p><b> }</b></p><p><b> }</b></p><p> for (j = 0; j <= p; j++)</p><p> p2->dat[j] = atoi(dat[j]);</p><p><b> }</b>&l
93、t;/p><p><b> }</b></p><p><b> else</b></p><p><b> {</b></p><p> for(m = 0; m < p2->num; m++)</p><p> p2->dat
94、[m] = 0;</p><p><b> }</b></p><p><b> }</b></p><p> else if(strchr(a_line, '=') != NULL)</p><p><b> {</b></p><
95、p> sscanf(a_line, "%*[^=]=%s", dat[0]);</p><p> p2->dat[0] = atoi(dat[0]);</p><p> p2->num = 1;</p><p><b> }</b></p><p><b> el
96、se</b></p><p> p2->num = 1;</p><p> k = 0; m = 0; p = 0; q = 0;</p><p> p2->next = (struct byte_word *)malloc(sizeof(struct byte_word));</p><p> p2 = p2
97、->next;</p><p><b> continue;</b></p><p><b> }</b></p><p> s++; /*行數(shù)加1*/</p><p><b> }</b></p><p>&
98、lt;b> free(p1);</b></p><p><b> free(p2);</b></p><p> p1 = NULL;</p><p> p2 = NULL;</p><p><b> s = 0;</b></p><p> fcl
99、ose(pfIn);</p><p> fclose(pfOut);</p><p> pfIn = fopen(argv[1], "r");</p><p> pfOut = fopen(argv[2], "w");</p><p> while (!feof(pfIn)) /*第二次
100、掃描*/</p><p><b> {</b></p><p> fgets(a_line, MAX_LEN, pfIn);</p><p> if ((pcPos = strchr(a_line, '#')) != NULL)</p><p> *pcPos = '\0';<
101、;/p><p> n = sscanf(a_line, "%s", op_sym);</p><p> if ((n < 1) || (strcmp("BYTE", op_sym) == 0) || (strcmp("WORD", op_sym) == 0))</p><p><b> c
102、ontinue;</b></p><p> if (strchr(a_line, ':'))</p><p><b> {</b></p><p> sscanf(a_line, "%*s%s", op_sym);</p><p> strcpy(a_line, s
103、trchr(a_line, ':') + 1);</p><p><b> }</b></p><p> op_num = GetInstrCode(op_sym);</p><p> if(op_num > 33)</p><p><b> {</b></p&g
104、t;<p> printf("ERROR: %s is a invalid instruction! \n", a_line);</p><p><b> exit(-1);</b></p><p><b> }</b></p><p> fprintf(pfOut,"0
105、x%08lx\n",TransToCode(a_line, op_num));</p><p><b> s++;</b></p><p><b> }</b></p><p> for (p2 = head2, k = 0, m = 0; (p2 != NULL) && (p2->n
106、um > 0) && (p2->num < 66); p2 = p2->next)</p><p><b> {</b></p><p> if(p2->type == 1)</p><p><b> {</b></p><p> for(s =
107、 0, j = 0; s < p2->num; s++)</p><p><b> {</b></p><p> str[j] = p2->dat[s]; /*目的將數(shù)據(jù)倒序輸出*/</p><p><b> j++;</b></p><p> if(j == 4)&
108、lt;/p><p><b> {</b></p><p> fprintf(pfOut, "0x%02lx%02lx%02lx%02lx\n", str[3], str[2], str[1], str[0]);</p><p><b> j = 0;</b></p><p>&
109、lt;b> }</b></p><p><b> k++;</b></p><p><b> }</b></p><p><b> switch(j)</b></p><p><b> {</b></p><
110、p><b> case 1:</b></p><p> fprintf(pfOut, "0x%08lx\n", str[0]);</p><p><b> break;</b></p><p><b> case 2:</b></p><p>
111、 fprintf(pfOut, "0x%04lx%04lx\n", str[1], str[0]);</p><p><b> break;</b></p><p><b> case 3:</b></p><p> fprintf(pfOut, "0x00%02lx%02lx%02l
112、x\n", str[2], str[1], str[0]);</p><p><b> break;</b></p><p><b> case 4:</b></p><p> fprintf(pfOut, "0x%02lx%02lx%02lx%02lx\n", str[3], str[
113、2], str[1], str[0]);</p><p><b> break;</b></p><p><b> }</b></p><p><b> }</b></p><p> if(p2->type == 2)</p><p>&l
114、t;b> {</b></p><p> for(s = 0, j = 0; s < p2->num; s++)</p><p><b> {</b></p><p> str[j] = p2->dat[s];</p><p><b> j++;</b>&
115、lt;/p><p> if(j == 2)</p><p> fprintf(pfOut, "0x%04lx%04lx4\n", str[1], str[0]);</p><p><b> k += 2;</b></p><p><b> }</b></p>&
116、lt;p><b> switch(j)</b></p><p><b> {</b></p><p><b> case 1:</b></p><p> fprintf(pfOut, "0x%08lx\n", str[0]);</p><p>
117、<b> break;</b></p><p><b> case 2:</b></p><p> fprintf(pfOut, "0x%04lx%04lx\n", str[1], str[0]);</p><p><b> break;</b></p>&l
118、t;p><b> }</b></p><p><b> }</b></p><p><b> }</b></p><p> fprintf(pfOut, "0x%08lx\n", k);</p><p> fclose(pfIn);</
119、p><p> fclose(pfOut);</p><p><b> return 1;</b></p><p><b> }</b></p><p> int GetInstrCode(const char *op_sym)</p><p><b> {&l
120、t;/b></p><p><b> int i;</b></p><p> for (i = 0; i < INSTRS_COUNT; i++)</p><p><b> {</b></p><p> if(strcmp(g_instrs_name[i], op_sym) ==
121、 0)</p><p><b> {</b></p><p><b> break;</b></p><p><b> }</b></p><p><b> }</b></p><p><b> return i
122、;</b></p><p><b> }</b></p><p> unsigned long TransToCode(char *instr_line, int instr_num)</p><p><b> {</b></p><p> unsigned long op_co
123、de;</p><p> unsigned long arg1, arg2, arg3;</p><p> unsigned long instr_code = 0ul;</p><p> char op_sym[8], reg0[8], reg1[8], reg2[8];</p><p> unsigned long addr;&l
124、t;/p><p> int immed, port;</p><p><b> int n;</b></p><p> char a[50];</p><p> switch (instr_format[instr_num])</p><p><b> {</b><
125、;/p><p> case '1': /*第一種指令格式(HLT、RET、NOP、NOTC)的譯碼*/</p><p> op_code = instr_num;</p><p> instr_code = op_code << 27;</p><p><b>
126、; break;</b></p><p> case '2': /*第二種指令格式(JMP、CJMP、OJMP、CALL)的譯碼*/</p><p> n = sscanf(instr_line, "%s%s", op_sym, a);</p><p> if (n
127、< 2)</p><p><b> {</b></p><p> printf("ERROR:bad instruction format!\n");</p><p><b> exit(-1);</b></p><p><b> }</b>&
128、lt;/p><p> addr = SearchTab(a) * 4;</p><p> op_code = GetInstrCode(op_sym);</p><p> instr_code = (op_code << 27) | (addr & 0x00ffffff);</p><p><b> brea
129、k;</b></p><p> case '3': /*第三種格式指令(PUSH、POP)的譯碼*/</p><p> n = sscanf(instr_line, "%s %s", op_sym, reg0);</p><p> if (n < 2
130、)</p><p><b> {</b></p><p> printf("ERROR:bad instruction format!\n");</p><p><b> exit(-1);</b></p><p><b> }</b></p&
131、gt;<p> op_code = GetInstrCode(op_sym);</p><p> arg1 = GetRegNum(instr_line, reg0);</p><p> instr_code = (op_code << 27) | (arg1 << 24);</p><p><b> brea
132、k;</b></p><p> case '4': /*第四種格式指令(LOARB、LOADW、STOREB、STOREW)的譯碼*/</p><p> n = sscanf(instr_line, "%s %s %s", op_sym, reg0, &a);</p&
133、gt;<p> if (n < 3)</p><p><b> {</b></p><p> printf("ERROR:bad instruction format!\n");</p><p><b> exit(-1);</b></p><p>&
134、lt;b> }</b></p><p> addr = Search_BYTE_WORD(a);</p><p> op_code = GetInstrCode(op_sym);</p><p> arg1 = GetRegNum(instr_line, reg0);</p><p> instr_code = (
135、op_code << 27) | (arg1 << 24) | (addr & 0x00ffffff);</p><p><b> break;</b></p><p> case '5': /*第五種格式指令(LOADI、ADDI、SUBI)的譯碼*/<
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 眾賞文庫僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 八路搶答器(匯編程序)微機(jī)課程設(shè)計(jì)
- 微機(jī)原理課程設(shè)計(jì)---動畫心匯編程序設(shè)計(jì)
- 匯編程序設(shè)計(jì)語言翻譯機(jī)
- 匯編程序.rar
- 匯編程序.rar
- c語言程序課程設(shè)計(jì)--模擬螞蟻覓食
- c語言程序課程設(shè)計(jì)
- c語言課程設(shè)計(jì)--c語言投票程序
- 匯編程序指令總結(jié)
- c語言課程設(shè)計(jì)報(bào)告-模擬時(shí)鐘轉(zhuǎn)動程序
- 數(shù)控恒流源匯編程序的設(shè)計(jì)畢業(yè)論文
- c語言程序設(shè)計(jì)課程設(shè)計(jì)
- c語言課程設(shè)計(jì)源程序
- c語言課程設(shè)計(jì)---c語言小車動畫程序
- 匯編語言程序設(shè)計(jì)-課程設(shè)計(jì)
- 匯編語言程序設(shè)計(jì)課程設(shè)計(jì)
- c課程設(shè)計(jì)報(bào)告-- c語言程序設(shè)計(jì)
- arm指令系統(tǒng)與匯編程序設(shè)計(jì)
- 《c語言程序設(shè)計(jì)》課程設(shè)計(jì)報(bào)告
- c語言程序設(shè)計(jì)課程設(shè)計(jì)報(bào)告
評論
0/150
提交評論