mipsmips32

MIPS "fetch address not aligned on word boundary" error on l.s instruction


I've read through some Q&As about this error on here, but I still don't understand what it means. I have a code in which I try to calculate p(n, r) and I keep getting this error: "line 26: Runtime exception at 0x00400044: fetch address not aligned on word boundary 0x00000006". I don't understand how it's not aligned since to my own knowledge, I haven't manipulated the address.

# n and r are assumed to be integers and n > r

.data
    textN: .asciiz "enter n: "
    textR: .asciiz "enter r: "

.text
    main: 
        li $v0, 4
            la $a0, textN
            syscall
            li $v0, 6
            syscall
            move $t0, $v0
        
        li $v0, 4
            la $a0, textR
            syscall
            li $v0, 5
            syscall
            move $t1, $v0
        
            move $a0, $t0
            jal Factorial
            la $t7, ($v0)
            l.s $f0, ($t7)   #line 26
            
            sub $a0, $t0, $t1
            jal Factorial
            la $t7, ($v0)
            l.s $f1, ($t7)
            
            div.s $f12, $f0, $f1
            li $v0, 2
            syscall 
            jr $ra
            
        Factorial:
            beq $a0, 1, Exception
            
            subi $sp, $sp, 8
            sw $t0, ($sp)
            sw $t1, 4($sp)
            
            move $t0, $a0
            move $v0, $a0
            
            Loop:
                subi $t0, $t0, 1
                beq $t0, $zero, Exit
                sub $t1, $a0, $t0
                mul $v0, $v0, $t1
                
            Exit:
                lw $t0, ($sp)
                lw $t1, 4($sp)
                addi $sp, $sp, 8
                jr $ra
                
            Exception:
                addi $v0, $v0, 1
                jr $ra

At first, I hadn't included the la instruction and line 26 was l.s $f0, ($v0). I assumed that the current update to line 26 and 27 was what was missing, but the error I'm receiving has remained unchanged.


Solution

  • I think you're a bit confused about what parentheses really mean.

    li $t0,8
    move $t1,$t0  ;copy the number 8 from $t0 into $t1.
    lw $t2,($t0)  ;load the four bytes at memory address 0x00000008 into $t2
    

    Essentially, parentheses around a register are the pointer star * in C, and la $t0, myLabel is the same as typename* ptr = &myLabel;. (I used li in the example above because a memory address is a number itself, but that's not usually what you would do if you really were dereferencing a pointer.)

    Your function factorial is intended to return an int, so you don't want to dereference that value. Assembly has no type safety at all, and lets you treat any register as a pointer to memory at any time.

    The actual source of your error message, however, has to do with a limitation of the MIPS CPU. Your input value for the factorial function was 3, right? I could tell by the error message. Rather than trying to copy the number 6 to $f1 (which wouldn't work for other reasons) you were trying to load the 4 bytes at memory address 0x00000006. This won't work, because MIPS can't use lw or sw to read/write 32-bit values at memory addresses that aren't aligned, i.e. not a multiple of 4. Trying to do so will result in a runtime error. But it's clear that's not what you wanted to do anyway.