Substitution for %hi and %lo in MIPS - mips

lui $a0,%hi(grid)
lw $v1,24($fp)
nop
move $v0,$v1
sll $v0,$v0,4
subu $v0,$v0,$v1
addiu $v1,$a0,%lo(grid)
addu $v1,$v0,$v1
lw $v0,28($fp)
nop
addu $2,$3,$2
li $3,3 # 0x3
sb $3,0($2)
lui $v0,%hi(rows)
lb $v0,%lo(rows)($v0)
nop
sw $v0,32($fp)
and
lui $v0,%hi(rows)
lb $v0,%lo(rows)($v0)
nop
sw $v0,32($fp)
Also error for this code:
bne $v0,$zero,1f
spim: (parser) syntax error on line 183 of file cubic.s
bne $v0,$zero,1f
What can I do to modify the %hi and %lo in my first code, and could someone please explain the spim error. Thank you!

Related

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.
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.

Assembly MIPS: Cannot debug floating-point power function

I have been trying to implement a floating-point function in Assembly MIPS 32-bits, and I have not been able to pinpoint the exact fault. It seems to be in the mul.s $fd, $fsrc1, $fsrc2 command, since the contents of the specific floating-point register remain unchanged (I have checked this with syscalls as well, printing the contents in each case) but I seem to be unable to find the fix. Anyone got any ideas? Full code below:
.align 2
.data
number: .float 0.5
.text
.globl main
main:
li $a0, 3
l.s $f12, number
jal power
li $v0, 2
mtc1 $a0, $f0
syscall
li $v0, 17
syscall
power:
#Build stack
subu $sp,$sp,56 # Stack frame is 56 bytes long
sw $a0, 12($sp) # Save Argument 0 ($a0)
swc1 $f12, 8($sp) # Save Argument 1 ($a1) (integer arg)
sw $s0, 56($sp) # Save $s0
sw $s1, 52($sp) # Save $s1
swc1 $f20, 48($sp) # Save $f20
swc1 $f21, 44($sp) # Save $f21
sw $ra, 16($sp) # Save return address
sw $fp, 20($sp) # Save frame pointer
addiu $fp, $sp, 52
#-----------------------------------------------------------------------#
move $s0, $a0 #stores value of n
mov.s $f22, $f12 #stores value of x
li $s1, 0 #initialize counter with 0
powerLoop:
mul.s $f20, $f20, $f20 #y=y*y
addi $s1, $s1, 1 #increase counter
bgtu $s0, $s1, powerLoop #continue loop as long as counter<n
mov.s $f0, $f20 #return the results
#-----------------------------------------------------------------------#
#Pop stack
lw $a0, 12($sp) #Load back $a0
lwc1 $f12, 8($sp) #Load back $f12
lw $s0, 56($sp) # Load $s0
lw $s1, 52($sp) # Load $s1
lwc1 $f20, 48($sp) # Load $f20
lwc1 $f21, 44($sp) # Load $f21
lw $ra, 16($sp) # Restore old value of $ra
lw $fp, 20($sp) # Restore old value of $fp
addiu $sp, $sp, 56 # Pop stack
jr $ra
SOLVED:
Despite some errors in registers, the main error is in the
li $v0, 2
mtc1 $a0, $f0
syscall
FIX:
li $v0, 2
mov.s $f12, $f0
syscall
REASON: $f12 IS ALWAYS, due to convention, the floating-point argument, even for syscalls. It will not print the contents of $a0 but rather $f12!

MIPS errors with %hi and %lo

lui $v0,%hi(length)
lw $v1,%lo(length)($v0)
li $v0,3 # 0x3
bne $v0,$zero,1f
div $zero,$v1,$v0
break 7
mfhi $v0
mflo $v0
sw $v0,28($fp)
lw $a1,28($fp)
lui $v0,%hi(game_over)
addiu $a0,$v0,%lo(game_over)
jal printf
nop
When I try running this for my MIPS code, it comes up with this error:
Your program produced these errors:
spim: (parser) Unknown character on line 180 of file measurement.s
lui $v0,%hi(length)
spim: (parser) syntax error on line 181 of file measurement.s
Instruction references undefined symbol at 0x00400038
[0x00400038] 0x0c000000 jal 0x00000000 [init_measure] ; 159: jal init_measure
Do I need to substitute %hi and $lo for something else in the code?
EDIT For the following code:
sw $v0,16($fp)
lui $a0,%hi(grid)
lw $v1,12($fp)
nop
move $v0,$v1
sll $v0,$v0,4
subu $v0,$v0,$v1
addiu $v1,$a0,%lo(grid)
addu $v1,$v0,$v1
lw $v0,16($fp)
And
lui $v0,%hi(column)
lb $v0,%lo(column)($v0)
nop
sw $v0,12($fp)
lui $v0,%hi(column)
addiu $v1,$v0,%lo(column)
lw $v0,8($fp)
nop
addiu $v1,$v0,-1
lui $v0,%hi(growth)
sw $v1,%lo(growth)($v0)
b true
nop
Will I be substituting %hi and % lo it in a similar manner or differently?
Those seem to be operators not supported by spim. %LO(label) should give you the lowest half of the address of label, and %HI(label) the upper half.
You can substitute these two instructions:
lui $v0,%hi(length)
lw $v1,%lo(length)($v0)
with this:
la $v0,length
lw $v1,0($v0)
So we use la pseudoinstruction to load the whole address of the label onto a register (in the example $v0) then you directly load its memory contents using 0 as the lw offset. Note that la pseudoinstruction would use 2 instructions for an arbitrary label address (and leave $at with the upper half address).
Also note that in your code $v0 would still hold the upper half of the label address whereas in the second snippet it will contain the whole address.
Similarily, instead of
lui $v0,%hi(game_over)
addiu $a0,$v0,%lo(game_over)
you can just issue:
la $a0, game_over
In this case, your code would end with $a0 having the address of game_over label (as in the second snippet), and $v0 holding the lower half of that address. la pseudoinstruction will leave the upper half of the label on $at

MIPS Stack Segment can't be Expanded

I'm writing a function that should return the square root of a perfect square recursively as part of a longer assignment.
I was following this mathematical method before I reverted to an even simpler algorithm to see if the error would repeat itself and it did.
The following code:
.data
prompt: .asciiz "num2sqrt: "
.text
.globl main
sqrt:
# save return address & t0
addi $sp, $sp, -8
sw $ra, 0($sp)
sw $t0, 4($sp)
# t0 = n
move $t0, $a0
# a0 = n/2
srl $a0, $t0, 1
jal sqrtRecursor
#restore return address & t0
lw $t0, 4 ($sp)
lw $ra, 0 ($sp)
addi $sp, $sp, 8
jr $ra
sqrtRecursor:
# save return address & t1
addi $sp, $sp, -8
sw $ra, 0($sp)
sw $t1, 4($sp)
# square test
mult $a0, $a0
mflo $t1
beq $t1, $t0, returnAnswer
bne $t1, $t0, newGuess
#restore return address & t1
lw $t1, 4 ($sp)
lw $ra, 0 ($sp)
addi $sp, $sp, 8
jr $ra
returnAnswer:
move $v0, $a0
newGuess:
# t1 = (((x+1)*guess)/x)/2
# x+1
addi $t1, $t0, 1
# *guess
mult $a0, $t1
mflo $t1
# /x
div $t1, $t0
mflo $t1
# /2
srl $t1, $t1, 1
move $a0, $t1
jal sqrtRecursor
main:
#print "Enter num2sqrt: "
la $a0, prompt
li $v0, 4
syscall
#input num2sqrt
li $v0, 5
syscall
move $s1, $v0
move $a0, $s1
jal sqrt
# print result
move $a0, $v0
li $v0, 1
syscall
# end
li $v0, 10
syscall
returns the following error on QTSpim:
Can't expand stack segment by 12 bytes to 524288 bytes. Use -lstack # with # > 524288
which then hangs the app for a minute or so.
I've double checked that I'm saving and returning all my return addresses and used variables, and also attempted implementing the same algorithm in Java separately (which worked), but have yet been unable to figure out what I need to fix and where.
I've been able to implement a power function before this so I'm not a complete novice and am asking after putting in approximately 5 hours of research and debugging on this.
It could be a stack management problem or an if/else implementation error from the intuition I have about my own code.

How can I convert code with operands %lo %hi to MARS working code?

I don't know how to convert code below to code that would work on MARS. Any ideas? Whole code here: https://pastebin.com/2RRT60Rd
addiu $sp,$sp,-72
sw $31,68($sp)
sw $fp,64($sp)
move $fp,$sp
lui $2,%hi($LC0)
addiu $4,$2,%lo($LC0)
jal printf
nop
addiu $2,$fp,40
move $5,$2
lui $2,%hi($LC1)
addiu $4,$2,%lo($LC1)
jal __isoc99_scanf
nop
lui $2,%hi($LC2)
addiu $4,$2,%lo($LC2)
jal printf
nop
addiu $3,$fp,56
addiu $2,$fp,48
move $6,$3
move $5,$2
lui $2,%hi($LC3)
addiu $4,$2,%lo($LC3)
jal __isoc99_scanf
nop