Skip to content

Instantly share code, notes, and snippets.

@halferty
Created October 23, 2012 07:07
Show Gist options
  • Save halferty/3937367 to your computer and use it in GitHub Desktop.
Save halferty/3937367 to your computer and use it in GitHub Desktop.
MIPS assembly lights-out
.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