明天做LC-3的四子棋實驗,但是我想睡懶覺就今天把他做了,這個實驗挺難的,要寫好久還容易出bug,我把自己的思路和代碼分享一下,讓大家少走彎路
前置知識
在做實驗前要掌握LC-3的一些僞指令和操作
標號
標號 = 內存地址 (可以這麼粗略的理解,編譯器建立了名字到內存的映射)
僞操作
特性:相當於庫函數了,調用這些僞操作,編譯器自動幫你做一些工作,標號以.
開頭,下面給出標號的解釋表格
標號名 | 標號後跟的操作數 | 解釋 |
---|---|---|
.ORIG | 起始地址 | 這個彙編文件的起始地址 |
.END | 無 | 程序在此結束 |
.FILL | 數字n | 將這個地方用n填充 |
.STRINGZ | 字符串 | 將這個地方作爲字符串首地址,往後填充字符串,自動填充\0 |
用法:
.ORIG 0x3000 ; 程序在0x3000地址開始
.END ; 編譯在此停止 但不是停止程序
.FILL #123 ; 這個地址將被賦值 123 (十進制)
.STRINGZ "abc" ; 這個地址起始,往後四個地址是 a b c \0
TRAP僞指令
除了僞操作,還可以使用TRAP x__
的語句,實現系統的調用
值得注意的是,輸入輸出都要用到R0寄存器,所以保存寄存器R0的值,再用R0輸出信息,是非常關鍵的,也是導致輸出錯誤的一大原因
指令號 | 解釋 |
---|---|
TRAP x25 | 程序exit |
TRAP x23 | 打印輸入提示信息並且接受用戶的一個輸入字符(ASCII碼形式 )到R0低8位 |
TRAP x21 | 將R0中低8位的值以ASCII碼形式打印到屏幕上 |
TRAP x20 | 不帶輸入提示信息的輸入讀取 和 TRAP x23 類似 |
TRAP x22 | 將R0中的值作爲字符串首地址 連續輸出字符串直到遇到0 |
代碼塊(函數)調用
LC-3提供非常簡陋的方式調用代碼塊(尚不能稱之爲函數。。。
因爲所有代碼共享8個寄存器,所以調用代碼塊之前記得保存寄存器的值
不要試圖在一個 帶RET的 函數中調用另外的函數,可能會引發意想不到的bug,比如死機(是的我死機過
func ADD R0, R0, #1 ; 這個函數叫func 功能是R0++
RET
...... 其他代碼 ......
JSR func ; JSR + 標號即可調用(跳轉到標號然後再跳轉回來)
題目描述
四子棋是一款普遍流行的簡易型桌面遊戲,據說,虎克船長曾因專注於此遊戲而長期隱身在住所,當船員們發現船長的這一專長之後,他們稱這個遊戲爲“船長的情婦”。
四子棋是個雙人遊戲,兩人輪流下棋,棋盤由行和列組成的網格,每個選手每次下一個子直到兩人中有一人的棋子連成一條水平線、垂直線或者是對角線。
本實驗需要在LC-3中實現簡易版四子棋的遊戲,兩位選手通過鍵盤和輸出窗口輪流交互操作,棋盤由6 X 6的網格組成。
遊戲規則如下:
兩位選手依次輪流落子;
選手不能悔棋;
有子的地方不能繼續落子;
直到有一方的四個棋子能夠連成一條水平線、垂直線或者是對角線;
如果棋盤已滿,無人獲勝,則平局。
遊戲最初時應該打印空的棋盤,可以用ASCII碼"-" (即ASCII 碼 x002D)來表示該處爲空
“O”(ASCII 碼 x004F)表示第一位選手的棋子,“X” (ASCII 碼 x0058)來表示第二位選手的棋子
爲了讓棋盤更易於觀察,在各列間加一個空格,第6列之後不要添加,初始棋盤應該如下:
- - - - - -
- - - - - -
- - - - - -
- - - - - -
- - - - - -
- - - - - -
選手一始終先下第一步棋,然後兩者輪流落子,在每次落子之後,應該打印該選手的信息,提示他落子,以選手一爲例,應該打印信息如下:Player 1, choose a column:
爲了明確選手的落子的位置,該選手應該輸入數字1-6,然後回車,數字1-6指示在落子所在的列,從左到右,無需輸入行號,程序應默認從行號6到行號1遞減的順序填入該棋子若前後輸入的列號相同,則行號減一。
例如,如果選手第一次在左起第二列落子,應該輸入2,然後回車,則該棋子落在行6列2處,當後面輸入的列號再次爲2時,則將棋子落子行5列2處,以此類推,詳情見後續示例輸出。
程序應該確保選手輸入的數字對應正確的列的範圍,如果輸入不合理,應該輸出一條錯誤信息,提示該選手繼續輸入,例如,如果對於選手一:
Player 1, choose a column: D
Invalid move. Try again.
Player 1, choose a column: 7
Invalid move. Try again.
Player 1, choose a column:
程序應該一直提示該選手,直到輸入正確的數字,當用戶輸入完成,程序應通過顯示回饋給選手,然後通過換行符(ASCII 碼 x000A)換行。
當選手輸入成功後,程序應打印更新後的棋盤,並檢查是否有人獲勝,如果沒人獲勝,則輪到下一位輸入。
當其中一位獲勝或平局時,遊戲結束,程序顯示最後的棋盤情況並終(Halt)。例如,如果選手二有四子相連,應該輸出:
Player 2 Wins.
如果平局,程序應該輸出:
Tie Game.
示例輸出
- - - - - -
- - - - - -
- - - - - -
- - - - - -
- - - - - -
- - - - - -
Player 1, choose a column: 1
- - - - - -
- - - - - -
- - - - - -
- - - - - -
- - - - - -
O - - - - -
Player 2, choose a column: 2
- - - - - -
- - - - - -
- - - - - -
- - - - - -
- - - - - -
O X - - - -
Player 1, choose a column: 2
- - - - - -
- - - - - -
- - - - - -
- - - - - -
- O - - - -
O X - - - -
Player 2, choose a column: 3
- - - - - -
- - - - - -
- - - - - -
- - - - - -
- O - - - -
O X X - - -
Player 1, choose a column: 3
- - - - - -
- - - - - -
- - - - - -
- - - - - -
- O O - - -
O X X - - -
Player 2, choose a column: 1
- - - - - -
- - - - - -
- - - - - -
- - - - - -
X O O - - -
O X X - - -
Player 1, choose a column: 4
- - - - - -
- - - - - -
- - - - - -
- - - - - -
X O O - - -
O X X O - -
Player 2, choose a column: 4
- - - - - -
- - - - - -
- - - - - -
- - - - - -
X O O X - -
O X X O - -
Player 1, choose a column: 3
- - - - - -
- - - - - -
- - - - - -
- - O - - -
X O O X - -
O X X O - -
Player 2, choose a column: 4
- - - - - -
- - - - - -
- - - - - -
- - O X - -
X O O X - -
O X X O - -
Player 1, choose a column: 4
- - - - - -
- - - - - -
- - - O - -
- - O X - -
X O O X - -
O X X O - -
Player 1 Wins.
----- Halting the processor -----
提示:
- 參考程序在內存中分配36個空間來表示棋盤的每個位置
- 最簡單的遍歷棋盤的方法爲:如果該位置爲空,則存放0,如果該位置爲選手一的棋子,則存放1,如果爲選手二的棋子,則存放-1,這樣可以最大程度的使用狀態碼。
在下面文章的代碼中,我沒有聽取上述這個建議,我是用1和2來表示的,所以判斷時遇到不少麻煩。。。
- 記得所有的輸入和輸出使用ASCII字符,必要時自己轉換。
- 從鍵盤接收輸入時使用TRAP x20 (GETC),顯示字符時使用TRAP x20 和TRAP x21
(OUT),合適的地方使用子例程,每次子例程都應暫存和恢復要使用的寄存器,這樣有利於調試程序。 - 程序首行指定第一條指令的地址,即.ORIG x3000。
- 最後提交的文件爲connect4.asm,根據提交的說明上傳程序以便打分。
實現思路
流程
代碼首先讀取玩家1的輸入,判斷並輸出非法信息直到玩家輸入合法爲止,然後改變棋盤矩陣的值,接着輸出更新後的棋盤,然後判斷輸贏,如果未分出勝負,則繼續讀取玩家2的輸入,然後做同樣的操作,仍然未分出勝負則查看是否棋盤已滿,如果未滿則繼續,已滿則平局
判斷勝利思路
這裏我用1來表示玩家1的棋子,用2來表示玩家2的棋子,我們需要判斷4種情況:分別是橫向四連“—
”,縱向四連“|
”,斜向四連“\
”和”/
”
如圖:
- 枚舉起點(兩重循環),然後向下(或者是右方,斜下方)找4個格子
- 統計4個格子中,1出現的個數
- 如果1出現個數爲4,則玩家1獲勝
- 如果1出現次數爲0則玩家2獲勝
- 否則難分勝負,不做操作
枚舉起點的時候注意下標不要越界即可。斜着找的話,LDR指令不是有offset嘛,直接設置就行了,偏移量分別爲0,1,2,3 ,或者是 0,-1,-2,-3
—
判斷的循環:外循環(行)6次 內循環(列)3次
\
判斷的循環:外循環(行)3次 內循環(列)3次
/
判斷的循環:外循環(行)3次 內循環(列)3次
|
判斷的循環:外循環(行)3次 內循環(列)6次
如圖:枚舉起點的定義
矩陣存放與填寫
在內存中連續的方式存放矩陣,即開36個空間,然後0-6是第一行,依次類推
題目的輸入要求非常怪,是像俄羅斯方塊一樣,下落式的,指定列數,然後從下往上填對應的行數,所以我們填寫的思路也很怪
矩陣填寫思路:使用指針的思想
-
用一個數組存儲指向矩陣最後一行各個列的指針
-
然後通過輸入的數字作爲數組偏移,找到列指針
-
將列指針指向的內存改寫爲玩家標誌(1或者2)
-
將該指針指向上一行(指針-6即可,指向下一次輸入的位置)
重點就是輸入的列數作爲指針數組的偏移,找到對應列的指針,以及找到之後,指針要指向上一行(即指向下一次輸入的位置)
測試結果
代碼
; @program : 簡易四子棋遊戲LC-3
; @author : 李若龍 2018171028
; @last modify : 2020/5/26 18:44
; @explain : 用分割線----劃分不同代碼塊
.ORIG x3000
BRnzp pre_main ; 從main函數開始
; ----------------------------------------------------
; print 函數 打印矩陣 矩陣首地址存在mat0x標號
; 標號解釋:
; pr_l1 print loop 1 外循環
; pr_l2 print loop 2 內循環
; pr_c1 print case 1 情況1 這是玩家1的棋子
; pr_c2 print case 2 情況2這是玩家2的棋子
; pr_l2ed loop 2 end 循環2結束
print ST R0, save_R0 ; 保存寄存器
ST R1, save_R1
ST R2, save_R2
ST R3, save_R3
ST R4, save_R4
ST R5, save_R5
ST R6, save_R6
ST R7, save_R7
AND R1, R1, #0 ; R1=6
ADD R1, R1, #6
LEA R3, mat0x ; R3保存矩陣首地址
pr_l1 AND R2, R2, #0 ; R2=6
ADD R2, R2, #6
pr_l2 LDR R4, R3, #0 ; R4=M[R3]取矩陣數據
ADD R3, R3, #1 ; R3+=1
ADD R5, R4, #0 ; 跳轉判斷
BRz pr_c3
ADD R5, R4, #-1 ; mat=1表示玩家1棋子
BRz pr_c1
ADD R5, R4, #-2 ; mat=2表示玩家2棋子
BRz pr_c2
pr_c1 LD R0, p1 ; 情況1玩家1棋子
TRAP x21
BRnzp pr_l2ed
pr_c2 LD R0, p2 ; 情況2玩家2棋子
TRAP x21
BRnzp pr_l2ed
pr_c3 LD R0, no_p ; 情況3無棋子
TRAP x21
pr_l2ed LD R0, space ; 打印空格
TRAP x21
ADD R2, R2, #-1
BRp pr_l2 ; 循環2到此結束
LD R0, nextLi ; 打印回車
TRAP x21
ADD R1, R1, #-1
BRp pr_l1 ; 循環1到此結束
LD R0, save_R0 ; 恢復寄存器
LD R1, save_R1
LD R2, save_R2
LD R3, save_R3
LD R4, save_R4
LD R5, save_R5
LD R6, save_R6
LD R7, save_R7
RET
; ----------------------------------------------------
; judge1 函數 判斷縱向四連 | 的情況
; 標號解釋:
; j1_l1 judge 1 loop 1 外循環
; j1_l2 judge 1 loop 2 內循環
; j1_ad1 judge 1 add 1 下一個行指針+1處
; j1_ad2 , j1_ad3, j1_ad4 同上(if跳轉用)
judge1 ST R0, save_R0 ; 保存寄存器
ST R1, save_R1
ST R2, save_R2
ST R3, save_R3
ST R4, save_R4
ST R5, save_R5
ST R6, save_R6
ST R7, save_R7
; 判斷|
AND R1, R1, #0
ADD R1, R1, #3 ; R1=3外循環迭代器
LEA R3, mat0x ; R3首行地址
j1_l1 AND R2, R2, #0
ADD R2, R2, #6 ; R2=6內循環迭代器
j1_l2 ADD R4, R3, #-1 ; 獲取當前行地址(偏移-1從0開始)
ADD R4, R4, R2 ; R4計算列偏移地址
AND R5, R5, #0 ; R5記錄玩家1棋子數目
LDR R0, R4, #0
BRz j1_l2ed ; 如果遇到0直接break
ADD R0, R0, #-1
BRnp j1_ad1
ADD R5, R5, #1
j1_ad1 ADD R4, R4, #6 ; R4指向下一行
LDR R0, R4, #0
BRz j1_l2ed ; 如果遇到0直接break
ADD R0, R0, #-1
BRnp j1_ad2
ADD R5, R5, #1
j1_ad2 ADD R4, R4, #6 ; R4指向下一行
LDR R0, R4, #0
BRz j1_l2ed ; 如果遇到0直接break
ADD R0, R0, #-1
BRnp j1_ad3
ADD R5, R5, #1
j1_ad3 ADD R4, R4, #6 ; R4指向下一行
LDR R0, R4, #0
BRz j1_l2ed ; 如果遇到0直接break
ADD R0, R0, #-1
BRnp j1_ad4
ADD R5, R5, #1
j1_ad4 ADD R6, R5, #-4 ; 只要能走到這裏必定爲4個1或2
BRz winc1_pre ; 如果p1計數器爲4則p1贏
ADD R5, R5, #0
BRz winc2_pre ; 如果p1計數器爲0則p2贏
j1_l2ed ADD R2, R2, #-1
BRp j1_l2 ; 內循環到此結束
ADD R3, R3, #6 ; R3指向下一行
ADD R1, R1, #-1
BRp j1_l1 ; 外循環到此結束
; 判斷|結束
LD R0, save_R0 ; 恢復寄存器
LD R1, save_R1
LD R2, save_R2
LD R3, save_R3
LD R4, save_R4
LD R5, save_R5
LD R6, save_R6
LD R7, save_R7
RET
; ----------------------------------------------------
; judge2 函數 判斷斜向四連 \ 的情況
; 標號解釋:同judge1
judge2 ST R0, save_R0 ; 保存寄存器
ST R1, save_R1
ST R2, save_R2
ST R3, save_R3
ST R4, save_R4
ST R5, save_R5
ST R6, save_R6
ST R7, save_R7
; 判斷\
AND R1, R1, #0
ADD R1, R1, #3 ; R1=3外循環迭代器
LEA R3, mat0x ; R3首行地址
j2_l1 AND R2, R2, #0
ADD R2, R2, #3 ; R2=3內循環迭代器
j2_l2 ADD R4, R3, #-1 ; 獲取當前行地址(偏移-1從0開始)
ADD R4, R4, R2 ; R4計算列偏移地址
AND R5, R5, #0 ; R5記錄玩家1棋子數目
LDR R0, R4, #0
BRz j2_l2ed ; 如果遇到0直接break
ADD R0, R0, #-1
BRnp j2_ad1
ADD R5, R5, #1
j2_ad1 ADD R4, R4, #6 ; R4指向下一行
LDR R0, R4, #1
BRz j2_l2ed ; 如果遇到0直接break
ADD R0, R0, #-1
BRnp j2_ad2
ADD R5, R5, #1
j2_ad2 ADD R4, R4, #6 ; R4指向下一行
LDR R0, R4, #2
BRz j2_l2ed ; 如果遇到0直接break
ADD R0, R0, #-1
BRnp j2_ad3
ADD R5, R5, #1
j2_ad3 ADD R4, R4, #6 ; R4指向下一行
LDR R0, R4, #3
BRz j2_l2ed ; 如果遇到0直接break
ADD R0, R0, #-1
BRnp j2_ad4
ADD R5, R5, #1
j2_ad4 ADD R6, R5, #-4 ; 只要能走到這裏必定爲4個1或2
BRz winc1_pre ; 如果p1計數器爲4則p1贏
ADD R5, R5, #0
BRz winc2_pre ; 如果p1計數器爲0則p2贏
j2_l2ed ADD R2, R2, #-1
BRp j2_l2 ; 內循環到此結束
ADD R3, R3, #6 ; R3指向下一行
ADD R1, R1, #-1
BRp j2_l1 ; 外循環到此結束
; 判斷\結束
LD R0, save_R0 ; 恢復寄存器
LD R1, save_R1
LD R2, save_R2
LD R3, save_R3
LD R4, save_R4
LD R5, save_R5
LD R6, save_R6
LD R7, save_R7
RET
; ----------------------------------------------------
pre_main BRnzp p_main ; main函數過於遠 中轉
; ----------------------------------------------------
; 字符存放
space .FILL 0x20
no_p .FILL 0x2D
p1 .FILL 0x4F
p2 .FILL 0x58
nextLi .FILL 0x0D
; 矩陣存放
mat0x .FILL #0
.FILL #0
.FILL #0
.FILL #0
.FILL #0
.FILL #0
mat1x .FILL #0
.FILL #0
.FILL #0
.FILL #0
.FILL #0
.FILL #0
mat2x .FILL #0
.FILL #0
.FILL #0
.FILL #0
.FILL #0
.FILL #0
mat3x .FILL #0
.FILL #0
.FILL #0
.FILL #0
.FILL #0
.FILL #0
mat4x .FILL #0
.FILL #0
.FILL #0
.FILL #0
.FILL #0
.FILL #0
mat50 .FILL #0
mat51 .FILL #0
mat52 .FILL #0
mat53 .FILL #0
mat54 .FILL #0
mat55 .FILL #0
; 寄存器存放
save_R0 .FILL #0
save_R1 .FILL #0
save_R2 .FILL #0
save_R3 .FILL #0
save_R4 .FILL #0
save_R5 .FILL #0
save_R6 .FILL #0
save_R7 .FILL #0
; ----------------------------------------------------
p_main BRnzp main ; main函數過於遠 中轉
winc1_pre BRnzp winc1 ; 中轉
winc2_pre BRnzp winc2
; ----------------------------------------------------
; judge3 判斷斜向四連 / 的情況
; 標號解釋:同judge1
judge3 ST R0, save_R0 ; 保存寄存器
ST R1, save_R1
ST R2, save_R2
ST R3, save_R3
ST R4, save_R4
ST R5, save_R5
ST R6, save_R6
ST R7, save_R7
; 判斷/
AND R1, R1, #0
ADD R1, R1, #3 ; R1=3外循環迭代器
LEA R3, mat0x ; R3首行地址
j3_l1 AND R2, R2, #0
ADD R2, R2, #3 ; R2=3內循環迭代器
j3_l2 ADD R4, R3, #-1 ; 獲取當前行地址(偏移-1從0開始)
ADD R4, R4, R2 ; R4計算列偏移地址
ADD R4, R4, #3
AND R5, R5, #0 ; R5記錄玩家1棋子數目
LDR R0, R4, #0
BRz j3_l2ed ; 如果遇到0直接break
ADD R0, R0, #-1
BRnp j3_ad1
ADD R5, R5, #1
j3_ad1 ADD R4, R4, #6 ; R4指向下一行
LDR R0, R4, #-1
BRz j3_l2ed ; 如果遇到0直接break
ADD R0, R0, #-1
BRnp j3_ad2
ADD R5, R5, #1
j3_ad2 ADD R4, R4, #6 ; R4指向下一行
LDR R0, R4, #-2
BRz j3_l2ed ; 如果遇到0直接break
ADD R0, R0, #-1
BRnp j3_ad3
ADD R5, R5, #1
j3_ad3 ADD R4, R4, #6 ; R4指向下一行
LDR R0, R4, #-3
BRz j3_l2ed ; 如果遇到0直接break
ADD R0, R0, #-1
BRnp j3_ad4
ADD R5, R5, #1
j3_ad4 ADD R6, R5, #-4 ; 只要能走到這裏必定爲4個1或2
BRz winc1_pre ; 如果p1計數器爲4則p1贏
ADD R5, R5, #0
BRz winc2_pre ; 如果p1計數器爲0則p2贏
j3_l2ed ADD R2, R2, #-1
BRp j3_l2 ; 內循環到此結束
ADD R3, R3, #6 ; R3指向下一行
ADD R1, R1, #-1
BRp j3_l1 ; 外循環到此結束
; 判斷/結束
LD R0, save_R0 ; 恢復寄存器
LD R1, save_R1
LD R2, save_R2
LD R3, save_R3
LD R4, save_R4
LD R5, save_R5
LD R6, save_R6
LD R7, save_R7
RET
; ----------------------------------------------------
; judge4 判斷橫向四連 即 - 的情況
; 標號解釋:同judge1
judge4 ST R0, save_R0 ; 保存寄存器
ST R1, save_R1
ST R2, save_R2
ST R3, save_R3
ST R4, save_R4
ST R5, save_R5
ST R6, save_R6
ST R7, save_R7
; 判斷-
AND R1, R1, #0
ADD R1, R1, #6 ; R1=6外循環迭代器
LEA R3, mat0x ; R3首行地址
j4_l1 AND R2, R2, #0
ADD R2, R2, #3 ; R2=3內循環迭代器
j4_l2 ADD R4, R3, #-1 ; 獲取當前行地址(偏移-1從0開始)
ADD R4, R4, R2 ; R4計算列偏移地址
AND R5, R5, #0 ; R5記錄玩家1棋子數目
LDR R0, R4, #0
BRz j4_l2ed ; 如果遇到0直接break
ADD R0, R0, #-1
BRnp j4_ad1
ADD R5, R5, #1
j4_ad1 LDR R0, R4, #1
BRz j4_l2ed ; 如果遇到0直接break
ADD R0, R0, #-1
BRnp j4_ad2
ADD R5, R5, #1
j4_ad2 LDR R0, R4, #2
BRz j4_l2ed ; 如果遇到0直接break
ADD R0, R0, #-1
BRnp j4_ad3
ADD R5, R5, #1
j4_ad3 LDR R0, R4, #3
BRz j4_l2ed ; 如果遇到0直接break
ADD R0, R0, #-1
BRnp j4_ad4
ADD R5, R5, #1
j4_ad4 ADD R6, R5, #-4 ; 只要能走到這裏必定爲4個1或2
BRz winc1_pre ; 如果p1計數器爲4則p1贏
ADD R5, R5, #0
BRz winc2_pre ; 如果p1計數器爲0則p2贏
j4_l2ed ADD R2, R2, #-1
BRp j4_l2 ; 內循環到此結束
ADD R3, R3, #6 ; R3指向下一行
ADD R1, R1, #-1
BRp j4_l1 ; 外循環到此結束
; 判斷-結束
LD R0, save_R0 ; 恢復寄存器
LD R1, save_R1
LD R2, save_R2
LD R3, save_R3
LD R4, save_R4
LD R5, save_R5
LD R6, save_R6
LD R7, save_R7
RET
; ----------------------------------------------------
; 列指針存放
ptr0 .FILL #0
ptr1 .FILL #0
ptr2 .FILL #0
ptr3 .FILL #0
ptr4 .FILL #0
ptr5 .FILL #0
; ----------------------------------------------------
; main 函數 ,程序從這裏開始執行
; 標號解釋:
; ma_lp1 main loop 1 主函數循環1
; in1 main input 1 玩家1輸入
; in2 main input 2 玩家2輸入
; i1t2 input 1 test 2 玩家1輸入合法測試2
; i1ed input 1 end 輸入1測試結束
; 其他同理
; winc1 win case 1 玩家1獲勝
; winc2 win case 2 玩家2獲勝
; EOM End Of Main main函數結束
main AND R1, R1, #0 ; R1=18 迭代變量
ADD R1, R1, #15
ADD R1, R1, #3
JSR print
LEA R0, mat50 ; 列指針賦值
ST R0, ptr0
LEA R0, mat51
ST R0, ptr1
LEA R0, mat52
ST R0, ptr2
LEA R0, mat53
ST R0, ptr3
LEA R0, mat54
ST R0, ptr4
LEA R0, mat55
ST R0, ptr5
ma_lp1 ADD R0, R0, #0
in1 LEA R0, p1inp ; 打印輸入
TRAP x22
TRAP x20 ; 玩家1輸入
TRAP x21 ; 回顯
ADD R0, R0, #-16
ADD R0, R0, #-16
ADD R0, R0, #-16 ; 輸入-48 ascii轉數字
ADD R2, R0, #0 ; 輸出回車
LD R0, nextLi_
TRAP x21
ADD R0, R2, #0
BRp i1t2 ; 判斷輸入是否>'0'
LEA R0, err ; 輸出錯誤提示
TRAP x22
BRnzp in1
i1t2 ADD R2, R0, #-7 ; R2=輸入-'7'
BRn i1ed ; 判斷輸入是否<'7'
LEA R0, err
TRAP x22
BRnzp in1
i1ed AND R2, R2, #0
ADD R2, R2, #1 ; 玩家1填數字1
LEA R3, ptr0 ; R3取列指針地址
ADD R3, R3, R0 ; R3列指針按照輸入偏移
LDR R4, R3, #-1 ; 讀取指針數據
STR R2, R4, #0 ; 將數據寫入R3指向的地址
ADD R4, R4, #-6 ; 指針--
STR R4, R3, #-1 ; 將偏移後的值存回去
JSR print
JSR judge1 ; 判斷 | 輸贏
JSR judge2 ; 判斷 \ 輸贏
JSR judge3 ; 判斷 / 輸贏
JSR judge4 ; 判斷 - 輸贏
in2 LEA R0, p2inp ; 打印:請玩家2輸入
TRAP x22
TRAP x20 ; 玩家2輸入
TRAP x21
ADD R0, R0, #-16
ADD R0, R0, #-16
ADD R0, R0, #-16 ; 輸入-48 ascii轉數字
ADD R2, R0, #0 ; 輸出回車
LD R0, nextLi_
TRAP x21
ADD R0, R2, #0
BRp i2t2 ; 判斷輸入是否>'0'
LEA R0, err ; 輸出錯誤提示
TRAP x22
BRnzp in2
i2t2 ADD R2, R0, #-7 ; R2=輸入-'7'
BRn i2ed ; 判斷輸入是否<'7'
LEA R0, err
TRAP x22
BRnzp in2
i2ed AND R2, R2, #0
ADD R2, R2, #2 ; 玩家2填數字2
LEA R3, ptr0 ; R3取列指針地址
ADD R3, R3, R0 ; R3列指針按照輸入偏移
LDR R4, R3, #-1 ; 讀取指針數據
STR R2, R4, #0 ; 將數據寫入R3指向的地址
ADD R4, R4, #-6 ; 指針--
STR R4, R3, #-1 ; 將偏移後的值存回去
JSR print
JSR judge1 ; 判斷 | 輸贏
JSR judge2 ; 判斷 \ 輸贏
JSR judge3 ; 判斷 / 輸贏
JSR judge4 ; 判斷 - 輸贏
ADD R1, R1, #-1
BRp ma_lp1 ; 循環到此結束
LEA R0, draw ; 平局
TRAP x22
BRnzp EOM
winc1 LEA R0, p1win ; p1贏了
TRAP x22
BRnzp EOM
winc2 LEA R0, p2win ; p2贏了
TRAP x22
BRnzp EOM
EOM AND R0, R0, #0 ; main函數結束
; ----------------------------------------------------
; 字符存放
nextLi_ .FILL 0x0D
; 字符串存放
p1inp .STRINGZ "player1 choose a cloumn:"
p2inp .STRINGZ "player2 choose a cloumn:"
draw .STRINGZ "Tie Game\n"
err .STRINGZ "Invalid move. Try again.\n"
p1win .STRINGZ "player1 win\n"
p2win .STRINGZ "player2 win\n"
.END