家庭作业 - TICTACTOE - 解决问题

时间:2014-06-22 21:17:35

标签: assembly mips

  1. 嘿,伙计们,我在理解程序行为方面遇到了问题。我试图存储一个地址返回,但它一直被覆盖。这是功课,所以不要给我一个简单的答案!也许只是解释jal如何覆盖我的$s0注册。我不太明白它是如何可能的。我在代码中添加了注释,以便您可以看到循环发生的位置。
  2. 2

    .data                               # data segment for variables and strings
    
    # These are all the strings that will need to be outputted to the console
    
    title: .asciiz "Tic-Tac-Toe!\n\n"
    oprompt: .asciiz "O player: Please enter row/col, one per line:\n\n"
    xprompt: .asciiz "X player: Please enter row/col, one per line:\n\n"
    invposstr: .asciiz " is an invalid position. Try again.\n\n"
    owinstr: .asciiz "O  won  the  game,\n\n  exiting. . ."
    xwinstr: .asciiz "X  won  the  game,\n\n  exiting. . ."
    catstr: .asciiz "CAT  game,\n\n  exiting. . ."
    border: .asciiz "\n\n _ _ _ \n"
    
    # Initialze the board with 9 bytes
    
    board: .byte 'X','X','X','X','X','_','X','_','_' 
    
    .text                       # text segment for instructions
    
    main:                       # begin the main func
    
    li $v0, 4               #set v0 to print string
    la $a0, title               #set string to print (in $a0) as title
    syscall                 #execute
    
    li $s1, 0               #use s1 as the game counter (up to 9 turns)
    
    
    playerx:                #player x will always go first
    
    li $v0, 4               #prepare to print string
    la $a0, xprompt         #load the get move prompt
    syscall
    
    jal get_valid_move          #go get a valid move address
    
    # I am having trouble returning here
    
    li $t0, 'X'             #load asciiz code for X
    sb $t0, ($v0)               #store the X into the board address
    
    addi $s1, 1             #increment the game counter to next turn
    
    jal print_board         #after getting the move, print the board status
    
    # And here  
    
    playero:                #player o will always go second
    
    li $v0, 4               #prepare to print string
    la $a0, oprompt             #load the get move prompt
    syscall
    
    jal get_valid_move          #go get a valid move address    
    
    # And here
    
    li $t0, 'O'             #load asciiz code for O
    sb $t0, ($v0)               #store the O into the board address
    
    addi $s1, 1             #increment the game counter to next turn
    
    jal print_board         #after getting the move, print the board status
    
    # And here
    
    j playerx               #go back to player x turn
    
    
    # I store the current return address below (first time) 
    
    print_board:                #function to print the status of the board
    
    move $s0, $ra           #save the recent return address
    
    la $t1, board           #load the board address
    
    li $v0, 4           #set v0 to print string
    la $a0, border          #set string to print (in $a0) as prompt
    syscall             #execute
    
    li $t0, 0           #use as counter for loop
    
    
    loop:               #use loop to print 1 row at a time
    
        li $v0, 11      #prepare to print char
        li $a0, 124     #asciiz code for |
        syscall
    
        lb $a0, ($t1)       #load next byte from board
        li $v0, 11          #prepare to print char
        syscall
    
        addi $t1, $t1, 1        #increment address of board to next byte/char
        addi $t0, $t0, 1        #increment loop counter
    
        beq $t0, 3, rowend      #go print special stuff at end of row
        beq $t0, 6, rowend      #go print special stuff at end of row
        beq $t0, 9, rowend      #go print special stuff at end of row
    
        j loop              #go back to top
    
    rowend:
    
        li $a0, 124         #asciiz for |
        li $v0, 11          #prepare to print char
        syscall
    
        li $a0, 10          #ascizz for newline
        li $v0, 11          #prepare to print char
        syscall
    
        blt $t0, 9, loop        #unless at the last row, loop
    
        li $a0, 10          #ascizz for newline
        li $v0, 11          #prepare to print char
        syscall
    
        jr $ra              #return to the gameplay in main
    
    
    entry_address:                  #function to transform user input (row, col) into board address
    
    move $t0, $a1                   #make a copy of row for use
    move $t1, $a2               #make a copy of col for use     
    addi $t0, $t0, -1           #use n-1 for accessing storage address
    addi $t1, $t1, -1           #use n-1
    mul $t0, $t0, 3             #mul the row by 3
    la $v0, board               #load base address of the board
    add $v0, $v0, $t0           #add the row offset
    add $v0, $v0, $t1           #add the col offset
                    #v0 now holds the correct board position address
    
    jr $ra                  #now go back to check if valid move
    
    
    valid_position:
    
    li $v0, 1           #assume valid
    blt $a1, 1, inv         #if row is less than 1
    bgt $a1, 3, inv         # or if row is greater than 3
    blt $a2, 1, inv         # or if col is less than 1
    bgt $a2, 3, inv         # or if col is greater than 3 change validity
    
    jr $ra              #go back to get_valid_move at last instruction
    
    inv:
    li $v0, 0           #since branched, change to inv
    jr $ra              #go back to get_valid_move at last instruction
    
    
    # I store the current return address into s0 below (the 2nd time)
    
    get_valid_move:
    
    move $s0, $ra           #save the recent return address
    
    li $v0, 5           #prepare to read row int
    syscall
    move $a1, $v0           #copy the read int into argument to be passed
    li $v0, 5           #prepare to read col int
    syscall
    move $a2, $v0           #copy the read int into argument to be passed
    
    jal valid_position      #go make sure pos is valid
    beq $v0, 0, invalid     #go tell user if valid_position returned false 
    
    jal entry_address       #position was good so go get entry_address
    
    # THE JR STATEMENT BELOW IS LOOPING BACK HERE
    # I need to return to the last instruction in main which I thought I stored in $s0
    
    li $t0, '_'         #use underscore for comparison
    lb $t1, ($v0)           #load the byte from the entry_address
    bne $t0, $t1, invalid           #if entry is taken, get another move
    
    jr $s0              #since move was valid go back to gameplay in main
    
    invalid:
    
        li $v0, 1       #prepare to print int
        move $a0, $a1       #load row numb
        syscall
        li $v0, 11      #prepare to print char
        li $a0, 44      #load comma asciiz
        syscall
        li $v0, 1       #prepare to print int
        move $a0, $a2       #load col numb
        syscall
        li $v0, 4       #prepare to print string
        la $a0, invposstr   #load invalid pos message
        syscall
    
        j get_valid_move    #repeat the user input loop
    
    
    check_all_match:
    print_winner_and_exit:
    row_winner:
    col_winner:
    diag_winner:
    check_for_win:
    
    # After printing all the results, we can exit the program
    exit:
    
    li $v0, 10              # set v0 to exit
    syscall                 # execute exit
    

0 个答案:

没有答案