LC3 仿真器的安裝和使用


最近想看計算機方面的經典教材《計算機系統概論》, 但是它上面的實例全部是在 LC3 仿真器環境下編寫的。要學習需要首先安裝 LC3 simulator 。 

安裝 lc3 仿真器的方法:
1. 到官網下載 lc3 模擬器和 lc3 編譯器(網址:http://highered.mheducation.com/sites/0072467509/student_view0/lc-3_simulator_lab_manual.html)。
下載解壓縮后,我將其放在 /home/david/Public/LC3_simulator目錄下。下載下來的都是源碼文件,我們需要做的就是手動編譯下。
2. 命令行切換到 /home/david/Public/LC3_simulator/lc3tools 目錄下, 根據README描述,安裝模擬器需要gcc、flex、wish這三個組件。其實Ubuntu
自帶了 gcc 和 wish, 只需要安裝 flex 即可。那么 sudo apt install flex 安裝即可。
3. 輸入 ./configure
4. 用 gedit 打開 Makefile 文件,找到一句“OS_SIM_LIBS = -lcurses”,把其中的“-lcurses”刪掉后保存。
5. 回到終端, 輸入 make 編譯成功。 終端中輸入 ./lc3sim 即可打開模擬器。
6. 模擬器安裝完成了,下面就是編譯器了。cd ../lcc-1.3 來到編譯器的目錄。同樣是閱讀README文件,輸入 ./configure 提示權限不足,用 sudo ./configure 還是不行,這時我們需要強制使用sh來運行這個腳本。完整的命令為:sudo sh ./configure。(出現上述問題的原因是那個configure腳本沒有加上可執行的權限,所以我們需要sudo sh來強制讓它執行。解決辦法為:先輸入chmod +x configure,然后就可以正常以./configure的方式來執行了。)輸入賬戶密碼后便可以了。接下來輸入“make”和“make install”來編譯源碼並安裝。
7. 安裝結束后,二進制可執行文件會存放在該目錄下/install/的文件夾中,其中的lcc便是編譯器的主程序。它同樣是一個命令行程序,不帶參數輸入./lcc便可以看到用法說明。
8. 試着把一個 C 程序翻譯成LC-3 匯編指令:
用 gedit 編寫 C 程序:

int main()
{
printf("Hello, world! \n");
return 0;
}

保存為 test.c 文件。
在終端切換到 install目錄下,執行:./lcc test.c, 會在同層目錄下自動生成 a.asm 文件,打開之后發現文件居然這么長。。。
以下是自動編譯成的 LC-3 匯編指令:

.Orig x3000
INIT_CODE
LEA R6, #-1
ADD R5, R6, #0
ADD R6, R6, R6
ADD R6, R6, R6
ADD R6, R6, R5
ADD R6, R6, #-1
ADD R5, R5, R5
ADD R5, R6, #0
LD R4, GLOBAL_DATA_POINTER
LD R7, GLOBAL_MAIN_POINTER
jsrr R7
HALT

GLOBAL_DATA_POINTER .FILL GLOBAL_DATA_START
GLOBAL_MAIN_POINTER .FILL main
;;;;;;;;;;;;;;;;;;;;;;;;;;;;main;;;;;;;;;;;;;;;;;;;;;;;;;;;;
main
ADD R6, R6, #-2
STR R7, R6, #0
ADD R6, R6, #-1
STR R5, R6, #0
ADD R5, R6, #-1

ADD R6, R6, #-1
ADD R7, R4, #3
ADD R6, R6, #-1
STR R7, R6, #0
ADD R0, R4, #1
LDR R0, R0, #0
jsrr R0
LDR R7, R6, #0
ADD R6, R6, #1
ADD R7, R4, #2
ldr R7, R7, #0
lc3_L1_/home/david/Desktop/test
STR R7, R5, #3
ADD R6, R5, #1
LDR R5, R6, #0
ADD R6, R6, #1
LDR R7, R6, #0
ADD R6, R6, #1
RET

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;    void printf(const char *format, ...)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

PRINTF_PERCENT .FILL -37
PRINTF_C .FILL -99
PRINTF_D .FILL -100
PRINTF_S .FILL -115
PRINTF_B .FILL -98
PRINTF_O .FILL -111
PRINTF_X .FILL -120
PRINTF_ASCII .FILL 48         ;postive ascii value of '0'
.FILL 49
.FILL 50
.FILL 51
.FILL 52
.FILL 53
.FILL 54
.FILL 55
.FILL 56
.FILL 57
.FILL 65        ;A
.FILL 66
.FILL 67
.FILL 68
.FILL 69
.FILL 70
PRINTF_MINUS .FILL 45  
PRINTF_BUF .BLKW 18
 

lc3_printf
ADD R6, R6, #-2
STR R7, R6, #0        ;return address
ADD R6, R6, #-1
STR R5, R6, #0
ADD R5, R6, #-1

ADD R6, R6, #-1
STR R4, R6, #0

ADD R5, R5, #4        ;cheating with the bp (no longer bp)
LDR R4, R5, #0        ;got addr of format string


PRINTF_LOOP    ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

LDR R0, R4, #0

ADD R0, R0, #0        ;End of string? (0x0000)
BRz PRINTF_DONE

ADD R2, R0, #0
LD R1, PRINTF_PERCENT
ADD R2, R2, R1
BRnp PRINTF_CHAR        

ADD R4, R4, #1
LDR R0, R4, #0
;is it %c?
ADD R2, R0, #0
LD R3, PRINTF_C
ADD R2, R2, R3
BRnp PRINTF_CHECKSTR
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;%c
ADD R5, R5, #1
LDR R0, R5, #0

PRINTF_CHAR
OUT

ADD R4, R4, #1
BRnzp PRINTF_LOOP

PRINTF_CHECKSTR
;is it %s?
ADD R2, R0, #0
LD R7, PRINTF_S
ADD R2, R2, R7
BRnp PRINTF_CHECKDEC        

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;%s

ADD R5, R5, #1
LDR R0, R5, #0
PUTS

ADD R4, R4, #1
BRnzp PRINTF_LOOP

PRINTF_CHECKDEC
;is it %d?
ADD R2, R0, #0
LD R7, PRINTF_D
ADD R2, R2, R7
;BRnp PRINTF_ERROR
BRnp PRINTF_CHECKHEX

AND R2, R2, #0
ADD R2, R2, #-10        ;going to divide by 10 by using sub loop
BRnzp PRINTF_NUM

PRINTF_CHECKHEX

ADD R2, R0, #0
LD R7, PRINTF_X
ADD R2, R2, R7
BRnp PRINTF_CHECKOCT

AND R2, R2, #0
ADD R2, R2, #-16        ;going to divide by 10 by using sub loop
BRnzp PRINTF_NUM

PRINTF_CHECKOCT

ADD R2, R0, #0
LD R7, PRINTF_O
ADD R2, R2, R7
BRnp PRINTF_CHECKBIN

AND R2, R2, #0
ADD R2, R2, #-8        ;going to divide by 10 by using sub loop
BRnzp PRINTF_NUM

PRINTF_CHECKBIN

ADD R2, R0, #0
LD R7, PRINTF_B
ADD R2, R2, R7
BRnp PRINTF_ERROR

AND R2, R2, #0
ADD R2, R2, #-2        ;going to divide by 10 by using sub loop
;BRnzp PRINTF_NUM



;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;%d
PRINTF_NUM

LEA R7, PRINTF_BUF
ADD R7, R7, #15 
ADD R7, R7, #1 

;AND R2, R2, #0
;ADD R2, R2, #-10        ;going to divide by 10 by using sub loop

ADD R5, R5, #1            ;acquire the binary number
LDR R0, R5, #0

ADD R0, R0, #0
BRzp PRINTF_DECPOS 

NOT R0, R0                ;make num positive for sub loop
ADD R0, R0, #1

PRINTF_DECPOS

AND R3, R3, #0
ADD R3, R3, #-1

PRINTF_DIVLOOP
ADD R3, R3, #1            ;num/10 
ADD R0, R0, R2            ;R0 = num % 10 - 10
BRzp PRINTF_DIVLOOP

ADD R3, R3, #0
BRz PRINTF_LASTDIGIT

;LD R1, PRINTF_ASCII
;ADD R1, R1, R0
;NOT R2, R2
;ADD R1, R1, R2 
;ADD R1, R1, #1
;NOT R2, R2
;;;;;ADD R1, R1, #10
;STR R1, R7, #0
;ADD R7, R7, #-1            ;stored ascii value of one digit

LEA R1, PRINTF_ASCII
ADD R1, R1, R0
NOT R2, R2
ADD R1, R1, R2 
ADD R1, R1, #1
NOT R2, R2
LDR R1, R1, #0
STR R1, R7, #0
ADD R7, R7, #-1            ;stored ascii value of one digit

ADD R0, R3, #0            ;num/10

BRnzp PRINTF_DECPOS

PRINTF_LASTDIGIT

;LD R1, PRINTF_ASCII
;ADD R1, R1, R0
;ADD R1, R1, #10
;STR R1, R7, #0

LEA R1, PRINTF_ASCII
ADD R1, R1, R0
NOT R2, R2
ADD R1, R1, R2 
ADD R1, R1, #1
NOT R2, R2
LDR R1, R1, #0
STR R1, R7, #0            ;stored ascii value of highest order digit

LDR R0, R5, #0
ADD R0, R0, #0
BRzp PRINTF_DECSTRING

LD R0, PRINTF_MINUS        ;num was negative
ADD R7, R7, #-1
STR R0, R7, #0            ;stored ascii value negative sign

PRINTF_DECSTRING        ;print the calculated string
ADD R0, R7, #0
PUTS

ADD R4, R4, #1
BRnzp PRINTF_LOOP

PRINTF_ERROR
PRINTF_DONE

LDR R4, R6, #0        ;restore R4
ADD R6, R6, #1

LDR R5, R6, #0        ;restore bp
ADD R6, R6, #1

LDR R7, R6, #0        ;restore ret addr
ADD R6, R6, #1

RET

GLOBAL_DATA_START
L1_/home/david/Desktop/test .FILL lc3_L1_/home/david/Desktop/test
printf .FILL lc3_printf
L3_/home/david/Desktop/test .FILL #0
L2_/home/david/Desktop/test .STRINGZ "Hello, world! \n"
.END

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM