Created
October 23, 2012 07:07
-
-
Save halferty/3937367 to your computer and use it in GitHub Desktop.
MIPS assembly lights-out
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
.data | |
newline: .asciiz "\n" | |
.text | |
j Main | |
############################# | |
# Display_Board | |
# Outputs the board to the screen | |
############################# | |
Display_Board: | |
li $t0, 'a' # Letter to print | |
li $t1, 16777216 # Bit mask (this is equal to 100000000000000000000000 in binary) | |
# Loop over rows | |
li $t2, 0 | |
loop_rows: | |
# Loop over columns | |
li $t3, 0 | |
loop_cols: | |
# Print each letter with the print character syscall | |
# Surrounded by spaces or parentheses depending on bit value | |
# print one leading space to keep this nicely formatted | |
li $a0, ' ' | |
li $v0, 11 | |
syscall | |
# Check the bit, and branch accordingly | |
and $t4, $t1, $s0 | |
beqz $t4, no_parens | |
# print parentheses | |
li $a0, '(' | |
li $v0, 11 | |
syscall | |
# Print the letter | |
add $a0, $0, $t0 | |
li $v0, 11 | |
syscall | |
li $a0, ')' | |
li $v0, 11 | |
syscall | |
j parens_done | |
no_parens: | |
# Print spaces instead | |
li $a0, ' ' | |
li $v0, 11 | |
syscall | |
# Print the letter | |
add $a0, $0, $t0 | |
li $v0, 11 | |
syscall | |
li $a0, ' ' | |
li $v0, 11 | |
syscall | |
parens_done: | |
# Increment the ASCII value of the letter to print. | |
add $t0, $t0, 1 | |
# print one trailing space to keep this nicely formatted | |
li $a0, ' ' | |
li $v0, 11 | |
syscall | |
# Right-shift the bit mask, so next iteration we check the next bit in $s0 | |
srl $t1, $t1, 1 | |
# Pause for 1/10th second. | |
#li $a0, 200 | |
#li $v0, 32 | |
#syscall | |
add $t3, $t3, 1 | |
bne $t3, 5, loop_cols | |
# Print a newline | |
la $a0, newline | |
li $v0, 4 | |
syscall | |
add $t2, $t2, 1 | |
bne $t2, 5, loop_rows | |
jr $ra | |
############################# | |
# Get_User_Input | |
############################# | |
Get_User_Input: | |
input_loop: | |
# Get a character | |
li $v0, 12 | |
syscall | |
# Loop until we get one in the a-y range | |
blt $v0, 'a', input_loop | |
bgt $v0, 'y', input_loop | |
# We want to return 0 for a, 1 for b, etc. | |
# ASCII 'a' is 97 so just subttract | |
# Note that whatever is in $v0 is by default the return value from this routine. | |
sub $t0, $v0, 'a' | |
# Print a newline to differentiate user input from program output | |
la $a0, newline | |
li $v0, 4 | |
syscall | |
add $v0, $0, $t0 | |
jr $ra | |
############################# | |
# Update_Board | |
############################# | |
Update_Board: | |
# This routine expects the chosen letter to be 0 if a, etc. | |
# However the state of the letters on the grid is stored from | |
# left to right. If $s0 = 0000000000000000000000000001 | |
# then only the lower right grid square is set. | |
# So adjust the input accordingly | |
li $t0, 16777216 # Start with a bit mask with the 25th bit set | |
srlv $t0, $t0, $a0 # Shift it right by the number of spaces specified | |
# Now if the input was 'a', $t0 contains 1000000000000000000000000 | |
# If the input were y, $t0 would equal 0000000000000000000000001 | |
# Now, when a square is selected, it and the four squares around it are inverted. | |
# Since we already have a bit mask for the square itself, inverting it is easy: | |
xor $s0, $s0, $t0 | |
# To invert/xor the squares above and below, we use the fact that if, say, the middle bit was chosen, | |
# then the square directly above it is represented by the bit 5 bits to the left. Since: | |
# 00000 | |
# 00000 | |
# 00100 | |
# 00000 | |
# 00000 | |
# is represented as 0000000000001000000000000 in $s0 | |
srl $t1, $t0, 5 | |
xor $s0, $s0, $t1 | |
sll $t1, $t0, 5 | |
xor $s0, $s0, $t1 | |
# To invert the squares to the right and left, we have to make sure the square isn't on the edge | |
# of the grid. If so, only invert the other side. | |
beq $a0, 5, only_right | |
beq $a0, 10, only_right | |
beq $a0, 15, only_right | |
beq $a0, 20, only_right | |
beq $a0, 4, only_left | |
beq $a0, 9, only_left | |
beq $a0, 14, only_left | |
beq $a0, 19, only_left | |
# If the square isn't on the edge, set both left and right: | |
srl $t1, $t0, 1 | |
xor $s0, $s0, $t1 | |
sll $t1, $t0, 1 | |
xor $s0, $s0, $t1 | |
j lr_done | |
only_right: | |
srl $t1, $t0, 1 | |
xor $s0, $s0, $t1 | |
j lr_done | |
only_left: | |
sll $t1, $t0, 1 | |
xor $s0, $s0, $t1 | |
lr_done: | |
jr $ra | |
############################# | |
# Check_For_End | |
############################# | |
Check_For_End: | |
# Checks the 25 rightmost bits of $s0. If they are all set, terminate the program. | |
li $t0, 33554431 # Equal to 0000 0001 1111 1111 1111 1111 1111 1111 | |
and $t0, $t0 , $s0 | |
bnez $t0, not_done # Return if some squares are on | |
# Otherwise, terminate the program | |
li $v0, 17 | |
syscall | |
not_done: | |
jr $ra | |
############################# | |
# Main | |
# Setup, main loop | |
############################# | |
Main: | |
# Put a random number in $s0 | |
li $v0, 41 | |
syscall | |
add $s0, $0, $a0 | |
# Loops forever. Check_For_End terminates the program | |
main_loop: | |
jal Display_Board | |
jal Get_User_Input | |
add $a0, $0, $v0 | |
jal Update_Board | |
jal Check_For_End | |
j main_loop |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment