Search code examples
assemblymipsmips32

How do i properly save return adress in mips before using jump and link to ensure i get backto where i was


When returning from a jump and link it seems i am not returning to the correct address and i dont know why

    .data
    fprompt: .asciiz "Jep numrin e antarve te vektorit (max 5): "
    sprompt: .asciiz "\nShtyp elementet nje nga nje: \n"

.text
.globl main

populloVektorin:
    addi $sp, $sp, -12   # Create space for local variables on the stack
    sw $s0, 0($sp)
    sw $s1, 4($sp)
    sw $s3, 8($sp)       # Save $s0, $s1, and $s3 on the stack
    move $s0, $a0       # Pointer to the array
    prompt:
        li $v0, 4            # Print string
        la $a0, fprompt      # Load string address
        syscall
        li $v0, 5            # Read integer
        syscall             # Read integer
        move $s1, $v0        # Save the number of array elements
        bgt $s1, 5, prompt  # If the number of elements is greater than 5, return
        li $v0, 4            # Print string
        la $a0, sprompt      # Load string address
        syscall             # Print string
        li $t0, 0           # Counter

    inputElement:
        blt $t0, $s1, loop1
        j loopExit1
    loop1:
        li $v0, 5
        syscall
        move $t1, $v0
        mul $t2, $t0, 4  # Calculate the offset (element_size * index)
        add $t3, $s0, $t2  # Calculate the address by adding the offset to the base address
        sw $t1, 0($t3)       # Store the element in the array
        addi $t0, $t0, 1
        j inputElement

    loopExit1:
        move $v0, $s1  # Return the number of elements
        lw $s0, 0($sp)  # Restore $s0
        lw $s1, 4($sp)  # Restore $s1
        lw $s3, 8($sp)  # Restore $s3
        addi $sp, $sp, 12  # Restore the stack pointer
        jr $ra

unazaKalimit:
    addi $sp, $sp, -24   # Create space for local variables on the stack
    sw $s0, 0($sp)
    sw $s1, 4($sp)
    sw $s2, 8($sp)       # Save $s0, $s1, and $s3 on the stack
    sw $s3, 12($sp)
    sw $s4, 16($sp)
    sw $ra, 20($sp)
     
    li $s0, 0 # s0 iterator
    move $s1, $a0 # s1 is the pointer to the array
    move $s2, $a1 # s2 is the number of array elements
    addi $t1, $s2, -1 # t1 is the last index
    for1:
        blt $s0, $t1, loop3  # if i < n-1
        j loopExit3
    loop3:
        mul $t4, $s0, 4  # t4 is the index of the current element
        add $t5, $s1, $t4  # Calculate the address by adding the offset to the base address
        lw $s3, 0($t5)  # Load the element using the calculated address
        move $s4, $s0  # current index
        move $a0, $s0
        move $a1, $s1
        move $a2, $s2
        # move $a0, $ra
        # li $v0, 1
        # syscall
        
        jal unazaVlerave
        
         
        lw $t5, 0($t5)  # Load the element using the calculated address
        sw $t5, 0($t5)  # Store the element in the array using the calculated address
        addi $s0, $s0, 1
        j for1

    loopExit3:
        lw $s0, 0($sp)  # Restore $s0
        lw $s1, 4($sp)  # Restore $s1
        lw $s2, 8($sp)  # Restore $s2
        lw $s3, 12($sp)  # Restore $s3
        lw $s4, 16($sp)  # Restore $s4
        lw $ra, 20($sp)
        addi $sp, $sp, 20  # Restore the stack pointer
        jr $ra

unazaVlerave:


    addi $sp, $sp, -12   # Create space for local variables on the stack
    sw $s0, 0($sp)
    sw $s1, 4($sp)
    sw $s2, 8($sp)
    move $s0, $a0  # s0 is the iterator
    move $s1, $a1  # s1 is the pointer to the array
    move $s2, $a2  # s2 is the number of array elements
    
    for:
        addi $s0, $s0, 1
        blt $s0, $s2, loop2
        loop2Exit:
        lw $s0, 0($sp)  # Restore $s0
        lw $s1, 4($sp)  # Restore $s1
        lw $s2, 8($sp)  # Restore $s2
        addi $sp, $sp, 12  # Restore the stack pointer
        move $a0, $ra
        li $v0, 1
        syscall
        
        jr $ra
    loop2:
        mul $t3, $s0, 4  # Calculate the offset (element_size * index)
        add $t4, $s1, $t3  # Calculate the address by adding the offset to the base address
        lw $s3, 0($t4)  # Load the element using the calculated address
        move $s4, $s0  # current index


        
        j for
    
       

main:
    li $v0, 9
    li $a0, 20
    syscall
    move $s0, $v0
    move $a0, $s0
    jal populloVektorin
    move $s1, $v0
    move $a0, $s0
    move $a1, $s1
    
    jal unazaKalimit
    

    li $v0, 10
    syscall

This is the code in its entirety, debugging this i found that after using jump return in the "for:" label it no longer takes me back to "unazaKalimit:" where the jump and link was called and instead throws an exception about bad memory.

This is an implementation of selection sort in the MIPS instruction set enter image description here


Solution

  • Just a simple typo, though one that can be found by reading the code or single stepping in the debugger.

    Function unazaKalimit allocates 24 bytes of stack on entry, while releasing only 20 bytes on exit.

    This will unbalance the stack and cause problems for its caller(s) as they try to use their own stack space upon resumption.  It is a requirement to restore the stack pointer to the incoming value upon return.