Objective Design and implement a MIPS assembly program, which plays a Gomoku game. The final program is about 250 lines. The purpose of this exercise is to make students practice assembly language programming including various control instructions, functions, and the runtime stack. |
Rules of a Free-Style Gomoku Game
It is a board game for two players who take turns in putting the pieces X and O on empty intersections of a board. The player’ goal is to create an unbroken row of certain pieces horizontally, vertically, or diagonally. The game ends when either the goal is achieved or winning by either player is not possible, e.g., the board being full. The winner of the game is the player achieving the goal first. Note that the online game on the right side is for demonstration only, and is not exact the game we want to implement. |
syscall
of MARS to randomly pick the system (X) or the user (O) to start the game.
syscall
32, sleep, of MARS to slow down the system’s move.
syscall
of MARS to randomly pick the next move for the system and the move has to be valid and shown (0..9, a..z).
. . . . . . 0 1 2 3 4 5 . . . . . . 6 7 8 9 a b . X . . . . c d e f g h . . . . . . i j k l m n . . . . . . o p q r s t . . . . . . u v w x y z
board: .ascii "\n\n . . . . . . 0 1 2 3 4 5" .ascii "\n . . . . . . 6 7 8 9 a b" .ascii "\n . . . . . . c d e f g h" .ascii "\n . . . . . . i j k l m n" .ascii "\n . . . . . . o p q r s t" .asciiz "\n . . . . . . u v w x y z\n" offset: .half 6, 8, 10, 12, 14, 16 .half 39, 41, 43, 45, 47, 49 .half 72, 74, 76, 78, 80, 82 .half 105, 107, 109, 111, 113, 115 .half 138, 140, 142, 144, 146, 148 .half 171, 173, 175, 177, 179, 181
won: .ascii "1237el6ci " # 0 .ascii "0232348fm7dj " # 1 .ascii "0131343459gn8ek " # 2 .ascii "0121242459fl8di " # 3 .ascii "123235agm9ej " # 4 .ascii "234bhnafk " # 5 .ascii "7890ciciodkr " # 6 .ascii "68989a0elels1djdjp " # 7 .ascii "67979a9ab2ekekq3di1fmfmt " # 8 .ascii "67878a8ab2gn3flflr4ejejo " # 9 .ascii "78989b4gmgmsfkp5fk " # a .ascii "89a5hnhntglq " # b .ascii "def06i6ioioujqx " # c .ascii "cefefg6krkry17j7jpjpv38i " # d .ascii "cdfdfgfgh07l7lslsz28k8kqkqw49j9jo" # e .ascii "cdedegegh18m8mt39l9lrlrx5akakpkpu" # f .ascii "defefh29n4amamsmsyblqlqv " # g .ascii "efg5bnbntntzmrw " # h .ascii "jkl06c6cocou38d " # i .ascii "iklklmcqx17d7dpdpv49e9eo " # j .ascii "ijljlmlmn6drdry28e8eqeqw5afafpfpu" # k .ascii "ijkjkmkmn07e7esesz39f9frfrxbgqgqv" # l .ascii "jklkln18f8ft4agagsgsyhrw " # m .ascii "klm29g5bhbhthtz " # n .ascii "pqr6ciciu9ej " # o .ascii "oqrqrs7djdjvafkfku " # p .ascii "oprprsrstcjx8ekekwbglglv " # q .ascii "opqpqsqst6dkdky9flflxhmw " # r .ascii "pqrqrt7elelzagmgmy " # s .ascii "qrs8fmbhnhnz " # t .ascii "ciofkpvwx " # u .ascii "uwxwxydjpglq " # v .ascii "uvxvxyxyzekqhmr " # w .ascii "uvwvwywyzcjqflr " # x .ascii "vwxwxzdkrgms " # y .ascii "wxyelshnt " # zwhere each three characters are the other three locations of four pieces in a row. For example, the move ‘p’ has the following winning combinations “
oqrqrs7djdjvafkfku
”:
opqr . . . . . . 0 1 2 3 4 5 pqrs . X . . X . 6 7 8 9 a b 7djp . X . X . . c d e f g h djpv . X X . . . i j k l m n afkp X X X X X . o p q r s t fkpu X X . . . . u v w x y zThe following program checks whether the next move wins the game. To make the script simple, the game is fixed and only the move ‘5’ or ‘p’ wins the game.
CheckWinning.asm
|
# ############# Checking a winning combination of Gomoku Game ############# # .data p1: .asciiz "\n\nEnter your move: (0..z) " p2: .asciiz "\nYou won!\n" board: .ascii "\n\n . . . . . . 0 1 2 3 4 5" .ascii "\n . . . . X . 6 7 8 9 a b" .ascii "\n . . . X . . c d e f g h" .ascii "\n . . X . . . i j k l m n" .ascii "\n . . . . . . o p q r s t" .asciiz "\n . . . . . . u v w x y z\n" offset: .half 6, 8, 10, 12, 14, 16 .half 39, 41, 43, 45, 47, 49 .half 72, 74, 76, 78, 80, 82 .half 105, 107, 109, 111, 113, 115 .half 138, 140, 142, 144, 146, 148 .half 171, 173, 175, 177, 179, 181 won: .ascii "1237el6ci " # 0 .ascii "0232348fm7dj " # 1 .ascii "0131343459gn8ek " # 2 .ascii "0121242459fl8di " # 3 .ascii "123235agm9ej " # 4 .ascii "234bhnafk " # 5 .ascii "7890ciciodkr " # 6 .ascii "68989a0elels1djdjp " # 7 .ascii "67979a9ab2ekekq3di1fmfmt " # 8 .ascii "67878a8ab2gn3flflrejo4ej " # 9 .ascii "78989b4gmgmsfkp5fk " # a .ascii "89a5hnhntglq " # b .ascii "def06i6ioioujqx " # c .ascii "cefefg6krkry17j7jpjpv38i " # d .ascii "cdfdfgfgh07l7lslsz28k8kqkqw49j9jo" # e .ascii "cdedegegh18m8mt39l9lrlrx5akakpkpu" # f .ascii "defefh29n4amamsmsylqvblq " # g .ascii "efg5bnbntntzmrw " # h .ascii "06c6cocou38djkl " # i .ascii "iklklmcqx17d7dpdpv49e9eo " # j .ascii "ijljlmlmn6drdry28e8eqeqw5afafpfpu" # k .ascii "ijkjkmkmn07e7esesz39f9frfrxbgqgqv" # l .ascii "jklkln18f8ft4agagsgsyhrw " # m .ascii "klm29g5bhbhthtz " # n .ascii "6ciciu9ejpqr " # o .ascii "oqrqrs7djdjvafkfku " # p .ascii "oprprsrstcjx8ekekwbglglv " # q .ascii "opqpqrqst6dkdky9flflxhmw " # r .ascii "pqrqrt7elelzagmgmy " # s .ascii "qrs8fmbhnhnz " # t .ascii "ciofkpvwx " # u .ascii "uwxwxydjpglq " # v .ascii "uvxvxyxyzekqhmr " # w .ascii "uvwvwywyzcjqflr " # x .ascii "vwxwxzdkrgms " # y .ascii "wxyelshnt " # z .text .globl main # ########################## Main Program ####################### # main: la $a0, board li $v0, 4 syscall # Print the game board. la $a0, p1 li $v0, 4 syscall # Print the prompt. # Read the next move. li $v0, 12 # Read a move (0..z). syscall # The syscall 12 is read char. move $s0, $v0 move $a0, $v0 # a0: the move in character jal MarkMove # Call the subroutine MarkMove. # Check the winning combination. move $a0, $s0 jal Convert move $t0, $a0 # $t0: the current move (0 - 35) jal EndGame la $a0, board li $v0, 4 syscall # Closing up li $v0, 10 # Exit. syscall # ######################### Mark a Move ######################### # # Input: $a0 (the move in character (0 - z)) # Output: MarkMove: # Save data in the runtime stack. subu $sp, $sp, 4 # Decrement the $sp to make space for $ra. sw $ra, ($sp) # Push/save the return address, $ra. subu $sp, $sp, 4 # Decrement the $sp to make space for $t0. sw $t0, ($sp) # Push/save the $t0. # Convert the move to an integer. bgt $a0, '9', L11 sub $t0, $a0, '0' j L12 L11: sub $t0, $a0, 'a' add $t0, $t0, 10 # Find the offset. L12: mul $t0, $t0, 2 # Each offset is two-byte long. lh $t1, offset($t0) # Load $t1 with the offset of the index $t0. # Mark the board. li $t2, 'X' # Put the piece ‘X’ in $t2. sb $t2, board($t1) # Put the piece at the location, board+offset. # Restore the data from the runtime stack. lw $t0, ($sp) # Pop/restore $t0. addu $sp, $sp, 4 # Increment the $sp. lw $ra, ($sp) # Pop/restore the return address, $ra. addu $sp, $sp, 4 # Increment the $sp. jr $ra # Return. # ########## Convert characters (including a - z) to numbers. ########## # # Input: $a0 (the move in character (0 - z)) # Output: $a0 (the move in 0 - 35) Convert: blt $a0, '0', L20 bgt $a0, '9', L20 sub $a0, $a0, '0' j L21 L20: sub $a0, $a0, 'a' add $a0, $a0, 10 L21: jr $ra # ######################## Check end of game. ############################ # # Input: $t0 (the move in 0 - 35) # Output: Declare the winning if won. EndGame: subu $sp, $sp, 4 sw $ra, ($sp) # Push the return address, $ra. li $t2, 1 # count for 11 rows or 33 bytes li $t5, 3 # 3 other pieces in a row mul $t1, $t0, 33 # t0: 0 - z (or 35) L30: lb $a0, won($t1) beq $a0, ' ', L32 jal Convert mul $a0, $a0, 2 lh $t3, offset($a0) lb $t4, board($t3) bne $t4, 'X', L31 sub $t5, $t5, 1 # Check the next location. add $t1, $t1, 1 bgt $t5, 0, L30 la $a0, p2 # Won li $v0, 4 syscall j L32 L31: add $t1, $t1, $t5 # Check the next 3 bytes. li $t5, 3 # the next 3 bytes add $t2, $t2, 1 blt $t2, 12, L30 L32: lw $ra, ($sp) # Pop the return address, $ra. addu $sp, $sp, 4 jr $ra # Return. |
syscall
of MARS such as:
xor $a0, $a0, $a0 # Set a seed number. li $a1, 36 # random number 0 to 35 li $v0, 42 # random number generator syscall # The random number is in $a0.Sample code of generating a random move is given below for your reference:
RandomMove.asm
|
# ###################### Generating a Random Move ###################### # # Input: # Output: $v0 (integer move), $v1 (integer offset) # RandomMove: subu $sp, $sp, 4 # Decrement the $sp to make space for $ra. sw $ra, ($sp) # Push/save the return address, $ra. subu $sp, $sp, 4 # Decrement the $sp to make space for $t0. sw $t0, ($sp) # Push/save the $t0. subu $sp, $sp, 4 # Decrement the $sp to make space for $t1. sw $t1, ($sp) # Push/save the $t1. R1: xor $a0, $a0, $a0 # Set a seed number. li $a1, 36 # random number from 0 to 35 li $v0, 42 # random number generator syscall # The random number is in $a0. move $t0, $a0 jal FindOffset # input: $a0 (move); output: $v1 (offset) lb $t1, board($v1) bne $t1, ' ', R1 # Go to R1 if the cell is not empty. move $v0, $t0 # $v0: the move in integer lw $t1, ($sp) # Pop/restore $t1. addu $sp, $sp, 4 # Increment the $sp. lw $t0, ($sp) # Pop/restore $t0. addu $sp, $sp, 4 # Increment the $sp. lw $ra, ($sp) # Pop the return address, $ra. addu $sp, $sp, 4 # Increment the $sp. jr $ra # Return. |
syscall
32, sleep, to slow down the system’s move.
routine1
is given as follows:
jal routine1 # Jump and link to routine1 next: ...where the label
next
is not required.
The following command in the subroutine routine1
will return the control back to the next
, the next command after the jal routine1
”:routine1: ... jr $ra # Jump to the contents of $rawhere the return address is saved in the register
$31
or $ra
$31
or $ra
, has to be saved before making the call.
The return address is restored after the called subroutine returns.
The instructor uses the runtime stack to save the return addresses, so deep subroutine calls are supported.
Use the following two commands to push the $ra
to the runtime stack:
subu $sp, $sp, 4 # Decrement the $sp to make space for $ra. sw $ra, ($sp) # Push the return address, $ra.and use the following two commands to pop up the
$ra
from the runtime stack:
lw $ra, ($sp) # Pop the return address, $ra. addu $sp, $sp, 4 # Increment the $sp.You may also use the runtime stack to save the register and variable values.
Examples of Exercise 2 Execution |
---|
Start Playing a Gomoku Game. . . . . . . 0 1 2 3 4 5 . . . . . . 6 7 8 9 a b . . . . . . c d e f g h . . . . . . i j k l m n . . . . . . o p q r s t . . . . . . u v w x y z You are the player O. Enter the next move: (0..z) l . . . . . . 0 1 2 3 4 5 . . . . . . 6 7 8 9 a b . . . . . . c d e f g h . . . O . . i j k l m n . . . . . . o p q r s t . . . . . . u v w x y z I (the System) am the player X and my move is w . . . . . . 0 1 2 3 4 5 . . . . . . 6 7 8 9 a b . . . . . . c d e f g h . . . O . . i j k l m n . . . . . . o p q r s t . . X . . . u v w x y z You are the player O. Enter the next move: (0..z) q . . . . . . 0 1 2 3 4 5 . . . . . . 6 7 8 9 a b . . . . . . c d e f g h . . . O . . i j k l m n . . O . . . o p q r s t . . X . . . u v w x y z I (the System) am the player X and my move is 8 . . . . . . 0 1 2 3 4 5 . . X . . . 6 7 8 9 a b . . . . . . c d e f g h . . . O . . i j k l m n . . O . . . o p q r s t . . X . . . u v w x y z You are the player O. Enter the next move: (0..z) v . . . . . . 0 1 2 3 4 5 . . X . . . 6 7 8 9 a b . . . . . . c d e f g h . . . O . . i j k l m n . . O . . . o p q r s t . O X . . . u v w x y z I (the System) am the player X and my move is 5 . . . . . X 0 1 2 3 4 5 . . X . . . 6 7 8 9 a b . . . . . . c d e f g h . . . O . . i j k l m n . . O . . . o p q r s t . O X . . . u v w x y z You are the player O. Enter the next move: (0..z) g . . . . . X 0 1 2 3 4 5 . . X . . . 6 7 8 9 a b . . . . O . c d e f g h . . . O . . i j k l m n . . O . . . o p q r s t . O X . . . u v w x y z You (O) won! New game? (y/n) y Start Playing a Gomoku Game. I (the System) am the player X and my move is 4 . . . . X . 0 1 2 3 4 5 . . . . . . 6 7 8 9 a b . . . . . . c d e f g h . . . . . . i j k l m n . . . . . . o p q r s t . . . . . . u v w x y z You are the player O. Enter the next move: (0..z) z . . . . X . 0 1 2 3 4 5 . . . . . . 6 7 8 9 a b . . . . . . c d e f g h . . . . . . i j k l m n . . . . . . o p q r s t . . . . . O u v w x y z I (the System) am the player X and my move is d . . . . X . 0 1 2 3 4 5 . . . . . . 6 7 8 9 a b . X . . . . c d e f g h . . . . . . i j k l m n . . . . . . o p q r s t . . . . . O u v w x y z You are the player O. Enter the next move: (0..z) u . . . . X . 0 1 2 3 4 5 . . . . . . 6 7 8 9 a b . X . . . . c d e f g h . . . . . . i j k l m n . . . . . . o p q r s t O . . . . O u v w x y z I (the System) am the player X and my move is s . . . . X . 0 1 2 3 4 5 . . . . . . 6 7 8 9 a b . X . . . . c d e f g h . . . . . . i j k l m n . . . . X . o p q r s t O . . . . O u v w x y z You are the player O. Enter the next move: (0..z) 0 O . . . X . 0 1 2 3 4 5 . . . . . . 6 7 8 9 a b . X . . . . c d e f g h . . . . . . i j k l m n . . . . X . o p q r s t O . . . . O u v w x y z I (the System) am the player X and my move is b O . . . X . 0 1 2 3 4 5 . . . . . X 6 7 8 9 a b . X . . . . c d e f g h . . . . . . i j k l m n . . . . X . o p q r s t O . . . . O u v w x y z You are the player O. Enter the next move: (0..z) t O . . . X . 0 1 2 3 4 5 . . . . . X 6 7 8 9 a b . X . . . . c d e f g h . . . . . . i j k l m n . . . . X O o p q r s t O . . . . O u v w x y z I (the System) am the player X and my move is e O . . . X . 0 1 2 3 4 5 . . . . . X 6 7 8 9 a b . X X . . . c d e f g h . . . . . . i j k l m n . . . . X O o p q r s t O . . . . O u v w x y z You are the player O. Enter the next move: (0..z) v O . . . X . 0 1 2 3 4 5 . . . . . X 6 7 8 9 a b . X X . . . c d e f g h . . . . . . i j k l m n . . . . X O o p q r s t O O . . . O u v w x y z I (the System) am the player X and my move is o O . . . X . 0 1 2 3 4 5 . . . . . X 6 7 8 9 a b . X X . . . c d e f g h . . . . . . i j k l m n X . . . X O o p q r s t O O . . . O u v w x y z You are the player O. Enter the next move: (0..z) 1 O O . . X . 0 1 2 3 4 5 . . . . . X 6 7 8 9 a b . X X . . . c d e f g h . . . . . . i j k l m n X . . . X O o p q r s t O O . . . O u v w x y z I (the System) am the player X and my move is a O O . . X . 0 1 2 3 4 5 . . . . X X 6 7 8 9 a b . X X . . . c d e f g h . . . . . . i j k l m n X . . . X O o p q r s t O O . . . O u v w x y z You are the player O. Enter the next move: (0..z) 6 O O . . X . 0 1 2 3 4 5 O . . . X X 6 7 8 9 a b . X X . . . c d e f g h . . . . . . i j k l m n X . . . X O o p q r s t O O . . . O u v w x y z I (the System) am the player X and my move is f O O . . X . 0 1 2 3 4 5 O . . . X X 6 7 8 9 a b . X X X . . c d e f g h . . . . . . i j k l m n X . . . X O o p q r s t O O . . . O u v w x y z You are the player O. Enter the next move: (0..z) c O O . . X . 0 1 2 3 4 5 O . . . X X 6 7 8 9 a b O X X X . . c d e f g h . . . . . . i j k l m n X . . . X O o p q r s t O O . . . O u v w x y z I (the System) am the player X and my move is g O O . . X . 0 1 2 3 4 5 O . . . X X 6 7 8 9 a b O X X X X . c d e f g h . . . . . . i j k l m n X . . . X O o p q r s t O O . . . O u v w x y z I (X) won! New game? (y/n) y Start Playing a Gomoku Game. ... We are tied! New game? (y/n) n -- program is finished running -- |
No. | Directive | Description | |
---|---|---|---|
1 | .ascii "string" |
Allocating space for string | |
2 | .asciiz "string" |
Allocating space for string, NULL terminated | |
3 | .byte |
Allocating space for a byte | |
4 | .data |
Beginning of data section | |
5 | .globl name |
Making the following name be a global symbol | |
6 | .half |
Allocating space for a half word (two bytes) | |
7 | .space n |
Allocating n bytes of space |
|
8 | .text |
Beginning of text section | |
No. | Instruction | Operation | Description |
1 | add rd, rs, rt |
rd = rs + rt |
Add;rd : destination register, rs : first source register, and rt : second source register or immediate value.Check MIPS Registers and Usage Convention. |
2 | addu rd, rs, rt |
rd = rs + rt (no overflow) |
Add unsigned |
3 | beq rs, rt, label |
if rs==rt then goto label |
Branch if equal to |
4 | bgt rs, rt, label |
if rs>rt then goto label |
Branch if greater than |
5 | ble rs, rt, label |
if rs≤rt then goto label |
Branch if less than or equal to |
6 | blt rs, rt, label |
if rs<rt then goto label |
Branch if less than |
7 | bne rs, rt, label |
if rs≠rt then goto label |
Branch if not equal to |
8 | bnez rs, label |
if rs≠0 then goto label |
Branch if not equal to zero |
9 | j label |
jump to label |
Jump |
10 | jal label |
jump to label and save the return address in $31 |
Jump and link |
11 | jr rs |
jump to [rs] ; [ ]: contents of |
Jump register |
12 | la rd, mem |
rd = address( mem ) |
Load address |
13 | lb rd, mem |
rd = mem |
Load byte |
14 | lh rd, mem |
rd = mem |
Load half word |
15 | li rd, imm |
rd = imm |
Load immediate |
16 | lw rd, mem |
rd = mem |
Load word |
17 | move rd, rs |
rd = rs |
Move register |
18 | mul rd, rs, rt |
rd = rs × rt |
Multiply |
19 | sb rs, mem |
mem = rs |
Store byte |
20 | sub rd, rs, rt |
rd = rs - rt |
Subtract |
21 | subu rd, rs, rt |
rd = rs - rt (no overflow) |
Subtract unsigned |
22 | sw rs, mem |
mem = rs |
Store word |
23 | syscall |
|
System call; check System Services. |
24 | xor rd, rs, rt |
rd = rs xor rt |
Bitwise exclusive or |
Service | Code in $v0 |
Arguments | Result |
---|---|---|---|
print_int | 1 | $a0 = integer to be printed |
|
print_float | 2 | $f12 = float to be printed |
|
print_double | 3 | $f12 = double to be printed |
|
print_string | 4 | $a0 = address of string in memory |
|
read_int | 5 | integer returned in $v0 |
|
read_float | 6 | float returned in $v0 |
|
read_double | 7 | double returned in $v0 |
|
read_string | 8 | $a0 = address of string input buffer$a1 = length of string buffer (n ) |
|
malloc | 9 | $a0 = amount |
address in $v0 |
exit | 10 | ||
print character | 11 | $a0 = character to be printed |
|
read character | 12 | character returned in $v0 |
|
sleep | 32 | $a0 = the length of time to sleep in milliseconds. |
Causes the MARS Java thread to sleep for (at least) the specified number of milliseconds. |
random int range | 42 | $a0 = i.d. of pseudorandom number generator (any int).$a1 = upper bound of range of returned values. |
$a0 contains pseudorandom, uniformly distributed int value
in the range 0 ≤ [int] < [upper bound], drawn from this random number generator’s sequence. |