2023年全國碩士研究生考試考研英語一試題真題(含答案詳解+作文范文)_第1頁
已閱讀1頁,還剩55頁未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(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)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論