实验报告

一、实验目的与要求

使用LC3汇编语言实现点格棋,根据英文指导文档实现各各模块之后再组合。

什么是点格棋?

Dots and Boxes is a two-player game played on a variable-size grid of dots. For this assignment, the playing board is a 4x4 grid of dots, and the two players are denoted by two symbols: 1 and 2

简单来说,就是使用连接点与点之间来实现圈地的游戏,谁最后将某个方块圈起来,那个方块就归谁,一个方块记一分,直到4x4下16个方块全都有所属时游戏结束。

二、实验步骤与过程

主要函数罗列:

大体在main函数里实现以下几个函数:

1、print_map():打印每次下棋后的地图

2、display_prompt():更新玩家控制权,控制棋子坐标输入和退出游戏

3、is_input_valid():检测坐标输入是否合法

4、is_occupied():检测输入的坐标是否已经被之前输入的占用

5、apply_move():实现棋子在地图上的更新

6、fill_box():重中之重,检测每次输入是否导致了玩家得分,并且将被圈起来的方块的占位符更新为队友玩家的编号

7、is_gameover():检测游戏是否达成结束条件

img

实现步骤一:C语言代码逻辑框架实现

LC3汇编语言属于机器语言,有多个函数的大工程不便于直接实现。在流程图的基础上,先用C语言写出了点格棋游戏。

img

img

实现步骤二:分模块化实现LC3程序

在C语言的框架下,我们一步一步翻译成LC3。

img

实现步骤三:编译和调试LC3代码

通过asm->编译代码,一开始出现了不少error,诸如未定义的label,语法错误等,有些错误是等到运行时才知道的,需要通过一步步debug来发现问题。

img

调试并排除完错误后,运行程序,得到正确结果:

img

三、实验结论或体会

通过此次实验,我学到了:

1、通过LC3仿真器运行和调试LC3代码,通过ide编写可执行的LC3代码。

2、磨炼了自己的心性,耐心地编写LC3汇编代码,并调试出错误。

3、通过阅读英语lab指导,提高了阅读计算机类英语文档的水平。

4、通过C->LC3的代码编写过程,熟悉了C语言在LC3框架上的底层实现。

5、对LC3的各种伪操作和命令有了更深入的理解。

附件:

点格棋c语言实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
#include<iostream>

/*data defination*/
int member = 1, current_mem = 1, sum = 0;
int r0, r1, r2, r3, r4;
int score[3] = {0};
char row_number, column_letter = 0;
char map[49];

/*function of every step*/
void initialize_map(){
for(int i = 0; i < 7; i++){
for(int j = 0; j < 7; j++){
map[7 * i + j] = ' ';
}
}

for(int i = 0; i < 7; i += 2){
for(int j = 0; j < 7; j += 2){
map[7 * i + j] = '*';
}
}
}
void print_map(){
printf("%d : %d\n", score[1], score[2]);
printf(" ABCDEFG\n");
for(int i = 0; i < 7; i++){
printf("%d", i);
for(int j = 0; j < 7; j++){
printf("%c", map[7 * i + j]);
}
printf("\n");
}
}

void display_prompt(){
current_mem = member;
if(member == 1){
printf("Player 1, input a move (or 'Q' to quit):");
member = 2;
}
else{
printf("Player 2, input a move (or 'Q' to quit):");
member = 1;
}
row_number = getchar();
if(row_number == 'Q'){
exit(0);
}
else{
column_letter = getchar();
}
char c = getchar();
}

void is_input_valid(){
/*r0 contains row number 0-6, r1 contains column letter A-G*/
r0 = row_number - '0';
r1 = column_letter - 'A';
if(((r0 % 2) && !(r1 % 2)) || (!(r0 % 2) && (r1 % 2))){
r3 = 0;
}
else{
r3 = -1;
}
}

void translate_move(){
/*it was implemented in "is_input_valid" */
}

void is_occupied(){
if(map[7 * r0 + r1] == ' '){
r3 = 0;
}
else{
r3 = -1;
}
}

void get_address(){

}

void apply_move(){
if(r0 % 2){
map[7 * r0 + r1] = '|';
}
else{
map[7 * r0 + r1] = '-';
}
}

void fill_box(){
if(map[7 * r0 + r1] == '|'){
if(r1 != 0){
if(map[7 * r0 + r1 - 2] == '|' && map[7 * (r0 - 1) + r1 - 1] == '-' && map[7 * (r0 + 1) + r1 - 1] == '-'){
map[7 * r0 + r1 - 1] = current_mem + '0';
r3 += 1;
}
}
if(r1 != 6){
if(map[7 * r0 + r1 + 2] == '|' && map[7 * (r0 - 1) + r1 + 1] == '-' && map[7 * (r0 + 1) + r1 + 1] == '-'){
map[7 * r0 + r1 + 1] = current_mem + '0';
r3 += 1;
}
}
}
if(map[7 * r0 + r1] == '-'){
if(r0 != 0){
if(map[7 * (r0 - 2) + r1] == '-' && map[7 * (r0 - 1) + r1 - 1] == '|' && map[7 * (r0 - 1) + r1 + 1] == '|'){
map[7 * (r0 - 1) + r1] = current_mem + '0';
r3 += 1;
}
}
if(r0 != 6){
if(map[7 * (r0 + 2) + r1] == '-' && map[7 * (r0 + 1) + r1 - 1] == '|' && map[7 * (r0 + 1) + r1 + 1] == '|'){
map[7 * (r0 + 1) + r1] = current_mem + '0';
r3 += 1;
}
}
}
score[current_mem] += r3;
sum += r3;
}

void is_gameover(){
if(sum == 16){
if(score[1] > score[2]){
printf("Game over. Player 1 is the winner!");
}
else{
printf("Game over. Player 2 is the winner!");
}
exit(0);
}
}

int main(){
initialize_map();
while(true){
print_map();
display_prompt();
is_input_valid();
if(r3 == -1){
printf("invalid input");
continue;
}
is_occupied();
if(r3 == -1){
printf("invalid input");
continue;
}
apply_move();
fill_box();
is_gameover()
}

return 0;
}

LC3源代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
.ORIG x3000

AND R5 R5 #0 ;R5存储游戏控制权,0是player1,1是player2
LOOP0 JSR print_map
JSR display_prompt

JSR is_input_valid
AND R0 R0 #0
ADD R0 R3 #1
BRz invalid_R3

JSR is_occupied
AND R0 R0 #0
ADD R0 R3 #1
BRz invalid_R3

JSR apply_move
JSR fill_box
JSR is_gameover
BRnzp DONE0
invalid_R3 LEA R0 invalid_input
PUTS
DONE0 BRnzp LOOP0

HALT
invalid_input .STRINGZ "\ninvalid_input\n"

is_gameover AND R6 R6 #0
ADD R6 R6 R7
LD R0 sum
ADD R0 R0 #-16
BRz over
AND R7 R7 #0
ADD R7 R7 R6
ret
over LD R3 score2
LD R0 score1
NOT R3 R3
ADD R3 R3 #1
ADD R0 R0 R3
BRp _1dayu2
LEA R0 p1_win
BRnzp _2dayu1
_1dayu2 LEA R0 p1_win
_2dayu1 PUTS
HALT
p1_win .STRINGZ "\nGame over. Player 1 is the winner!\n"
p2_win .STRINGZ "\nGame over. Player 2 is the winner!\n"

display_prompt AND R6 R6 #0
ADD R6 R6 R7
AND R5 R5 R5
BRz player1
BRp player2
ret
player1 LEA R0 p1
PUTS
ADD R5 R5 #1
BRnzp Getchar
player2 LEA R0 p2
PUTS
ADD R5 R5 #-1
Getchar GETC ;R1 R2 分别存储数字和字母
LD R1 char
ADD R1 R1 R0
BRz quit
AND R1 R1 #0
ADD R1 R1 R0
GETC
AND R2 R2 #0
ADD R2 R2 R0
AND R7 R7 #0
ADD R7 R7 R6
ret
quit HALT

char .FILL #-81
p1 .STRINGZ "Player 1, input a move (or 'Q' to quit):\n"
p2 .STRINGZ "Player 2, input a move (or 'Q' to quit):\n"



apply_move AND R6 R6 #0
ADD R6 R6 R1
ADD R6 R6 R6
ADD R6 R6 R6
ADD R6 R6 R6
ADD R6 R6 R1
ADD R6 R6 R2

AND R0 R1 #1
BRp jishu
LD R0 henggang
BRnzp oushu
jishu LD R0 shugang
oushu ADD R6 R6 R4
ST R6 address
STI R0 address
ret
shugang .FILL #124
henggang .FILL #45
_shugang .FILL #-124
_henggang .FILL #-45
sum .FILL #0
score1 .FILL #0
score2 .FILL #0

fill_box AND R3 R3 #0
ST R7 ret_address
ST R1 R_1 ;保存R1R2
ST R2 R_2
AND R0 R0 #0
ADD R0 R0 R1
ADD R0 R0 R0
ADD R0 R0 R0 ;同理R4[9 * R1 + R2]
ADD R0 R0 R0
ADD R0 R0 R1
ADD R0 R0 R2 ;R1R2到此步骤已经没有作用了,偏移已经存在R0
ADD R0 R0 R4

ST R0 address
LDI R6 address ;R6存变量上述的R4[]
LD R1 _shugang
ADD R1 R1 R6
BRz situation1
BRnzp situation2

situation1 LD R2 R_2
ADD R1 R2 #0
BRnp situation1_1
ADD R1 R2 #-6
BRnp situation1_2
situation1_1 LD R2 _henggang ;R2存横杠,R6存竖杆
LD R6 _shugang

ADD R1 R0 #-2
ST R1 address
LDI R1 address
ADD R1 R6 R1
BRnp end1

ADD R1 R0 #-10
ST R1 address
LDI R1 address
ADD R1 R2 R1
BRnp end1

ADD R1 R0 #8
ST R1 address
LDI R1 address
ADD R1 R2 R1
BRnp end1

ADD R1 R0 #-1
ST R1 address
JSR apply_get_score
ADD R3 R3 #1
end1 LD R1 R_1
ADD R1 R1 #-6
BRz situation1_2
BRnzp DONE2
situation1_2 LD R2 _henggang ;R2存横杠,R6存竖杆
LD R6 _shugang

ADD R1 R0 #2
ST R1 address
LDI R1 address
ADD R1 R6 R1
BRnp end2

ADD R1 R0 #-8
ST R1 address
LDI R1 address
ADD R1 R2 R1
BRnp end2

ADD R1 R0 #10
ST R1 address
LDI R1 address
ADD R1 R2 R1
BRnp end2

ADD R1 R0 #1
ST R1 address
JSR apply_get_score
ADD R3 R3 #1

end2 BRnzp DONE2
situation2 LD R1 R_1
ADD R2 R1 #0
BRnzp situation2_1
ADD R2 R1 #-6
BRnzp situation2_2
situation2_1 LD R2 _henggang ;R2存横杠,R6存竖杆
LD R6 _shugang

ADD R1 R0 #-9
ADD R1 R1 #-9
ST R1 address
LDI R1 address
ADD R1 R2 R1
BRnp end3

ADD R1 R0 #-10
ST R1 address
LDI R1 address
ADD R1 R6 R1
BRnp end3


ADD R1 R0 #-8
ST R1 address
LDI R1 address
ADD R1 R6 R1
BRnp end3

ADD R1 R0 #-9
ST R1 address
JSR apply_get_score
ADD R3 R3 #1

end3 LD R2 R_2
ADD R2 R2 #-6
BRz situation2_1
BRnzp DONE2
situation2_2 LD R2 _henggang ;R2存横杠,R6存竖杆
LD R6 _shugang

ADD R1 R0 #9
ADD R1 R1 #9
ST R1 address
LDI R1 address
ADD R1 R2 R1
BRnp DONE2

ADD R1 R0 #8
ST R1 address
LDI R1 address
ADD R1 R6 R1
BRnp DONE2


ADD R1 R0 #10
ST R1 address
LDI R1 address
ADD R1 R6 R1
BRnp DONE2

ADD R1 R0 #9
ST R1 address
JSR apply_get_score
ADD R3 R3 #1

DONE2 LD R7 ret_address
LD R0 sum
ADD R0 R3 R0
ST R0 sum
AND R5 R5 R5
BRz player1_get_score
BRnzp player2_get_score
player1_get_score LD R0 score1
ADD R0 R3 R0
ST R0 score1
ret
player2_get_score LD R0 score2
ADD R0 R3 R0
ST R0 score2
ret
;关键函数fillbox,R0 R3 R6可用,R3暂时用来存分数,R0用来存偏移后的地址
;R1 R2存行列,R4是map首地址,R5控制权,R7返回地址
map .STRINGZ " ABCDEFG\n0*#*#*#*\n1#######\n2*#*#*#*\n3#######\n4*#*#*#*\n5#######\n6*#*#*#*\n"
address .FILL #0
ret_address .FILL #0
R_1 .FILL #0
R_2 .FILL #0

is_input_valid AND R6 R6 #0
ADD R6 R6 R7

LD R0 num1
ADD R1 R1 R0
LD R0 char1
ADD R2 R2 R0

AND R0 R2 #1
AND R4 R1 #1

NOT R3 R0 ;异或操作
AND R3 R3 R4
NOT R4 R4
AND R0 R0 R4 ;R4释放掉
AND R4 R4 #0
NOT R0 R0
NOT R3 R3
AND R0 R0 R3
AND R3 R3 #0 ;R3赋值为0,有意义
NOT R0 R0
BRz invalid
AND R7 R7 #0
ADD R7 R7 R6
ret
invalid ADD R3 R3 #-1
AND R7 R7 #0
ADD R7 R7 R6
ret
num1 .FILL #-48
char1 .FILL #-65

is_occupied AND R6 R6 #0 ;9 * 8 的地图
ADD R6 R6 R7
LEA R4 map
ADD R4 R4 #10

AND R7 R7 #0
ADD R7 R1 R7
ADD R7 R7 R7
ADD R7 R7 R7
ADD R7 R7 R7
ADD R7 R7 R1 ;实现R1乘以10
ADD R7 R7 R2

ADD R7 R7 R4
ST R7 address
LDI R0 address
LD R7 space
ADD R0 R7 R0

BRz not_occupy
AND R3 R3 #0
ADD R3 R3 #-1
BRnzp DONE1
not_occupy AND R3 R3 #0

DONE1 AND R7 R7 #0
ADD R7 R7 R6
ret
space .FILL #-35

print_map AND R6 R6 #0
ADD R6 R6 R7
LEA R0 map
PUTS
AND R7 R7 #0
ADD R7 R7 R6
ret
apply_get_score AND R5 R5 R5
BRz apply_player1
LD R1 pl2
STI R1 address
ret
apply_player1 LD R1 pl1
STI R1 address
ret
pl1 .FILL x31
pl2 .FILL x32
.END