Branching in mips - if-statement

I'm new to mips and was trying make equivalent instructions from Java:
if (x == y)
z = 14;
else
w = 23;
I've come up with:
.data
w: .word 23
x: .word 1
y: .word 1
z: .word 14
.text
lw $t1 x
lw $t2 y
lw $t3 z
lw $t4 w
bne $t1, $t2, L1
j L2
L1: jr $t4
L2: jr $t3
but I get an error: invalid program counter value: 0x0000000e
I have no idea what is wrong. Any help in the right direction would be appreciated.

Jr means jump register and it is intended to be used when you have a function in MIPS. It's like return in C and many other languages. In your case you don't have a function so you don't need to return something. Your code should look something like this :
.data
w: .word 23
x: .word 1
y: .word 1
z: .word 14
.text
lw $t1 x
lw $t2 y
lw $t3 z
lw $t4 w
bne $t1, $t2, L1
L1:
#Do something
$v0,10
syscall
In the future you want to use jr or jal while most likely using a stack. Overtime you are calling a different function you want the compiler to have a "please to return", so you are saving the address each time in $ra(return address). In other words if you just want to use branching without calling a function you don't need to use jr.

I completely forgot to upload what I came up with. The next lesson my teacher covered was jr and jal.
.data
w: .word 23
x: .word 1
y: .word 1
z: .word 14
.text
lw $t1 x
lw $t2 y
bne $t1, $t2, L1
li $t5 14
sw $t5 z
j out
L1: li $t4 23
sw $t4 w
out:

Related

why jal main error (jal 0x00000000 [main])

When I run this code,There is an error in the main and it does not operate normally.
I changed the main function or thought there was a problem with the main and global main, so I repeated the correction several times.
.data
message: .asciiz " The final result is "
.text
.global main
main:
addi $a0, $zero, 3
addi $a1, $zero, 10
addi $a2, $zero, 15
addi $a3, $zero, 7
jal leaf_example
li $v0, 4
la $a0, message
syscall
li $v0, 1
syscall
leaf_example:
addi $sp, $sp,-12
sw $t1, 8
sw $t0, 4
sw $s0, 0
add $t0,$a0,$a1
add $t1,$a2,$a3
sub $s0,$t0,$t1
add $v0,$s0,$zero
lw $s0,0
lw $t0,4
lw $t1,8
addi $sp,$sp,12
jr $ra
spim: (parser) syntax error on line 4 of file
C:/Users/user/Desktop/qtspim16.asm .global main
^

Drawing on MIPS. Runtime error

have a problem with the following code. I wrote a code for drawig a quater circle on a MARS assembler. But there is an error occurring. The program itself draws the quater circle but in the end there is an error, because of it I cannot use a loop for this procedure, the code is below
.data
DISPLAY: .space 65536
DISPLAYWIDTH: .word 128
DISPLAYHEIGHT: .word 128
.text
j main
set_pixel_color:
mulu $t0 $a1 $s0
add $t0 $t0 $a0
mul $t0 $t0 4
la $t2 DISPLAY
add $t2 $t2 $t0
sw $a2 ($t2)
jr $ra
quater_circle:
add $a1 $0 0
add $a0 $0 0
lw $a2 RED
loop2:
jal set_pixel_color
add $a0 $a0 1
mulu $t3 $a0 $a0
mulu $t4 $a1 $a1
add $t3 $t3 $t4
mulu $t4 $a3 $a3
ble $t3 $t4 loop2
add $a0 $0 $0
add $a1 $a1 1
ble $a1 $a3 loop2
jr $ra
.data
RED: .word 0xff0000
GREEN: .word 0x00ff00
BLUE: .word 0x0000ff
.text
main:
lw $s0, DISPLAYWIDTH # s0 holds MAX x
lw $s1, DISPLAYHEIGHT # s1 holds MAX y
li $a3 1
lw $a2 BLUE
add $a0 $0 $0
add $a1 $0 $0
loop:
jal set_pixel_color
add $a0 $a0 1
ble $a0 127 loop
add $a0 $0 $0
add $a1 $a1 1
ble $a1 127 loop
draw:
jal quater_circle
add $a3 $a3 1
ble $a3 128 draw
It ends up with the drawn red quater circle with the blue backround, however it terminates in the end of the procedure, and I cannot use a draw procedure. Can you help me please?
You are losing $ra in your quater_circle subroutine.
That routine is called from main and it calls another subroutine (set_pixel_color), thus losing original return address.
You should preserve $ra in your quater_circle subroutine by storing its contents into the stack (and restoring it before returning to the caller) or alternatively moving $ra to some other register (e.g, $s2) and use it to return.
For the second alternative, you would add
move $s2, $ra
at the beginning of quater_circle subroutine and change
jr $ra
with
jr $s2
at the end of the subroutine.

If greater than or equal in MIPS

Prompt for and input two integers “a” and “b” using syscalls
Display one of the following statements depending on if a>b, or a=b or a
You entered a greater than b
You entered an equal to b
You entered a less than b
I have to get this prompt and I tried so hard to get it done. This is where I'm stucked, I'd really appreciate your help.
.data
p1: .asciiz "Please enter the first number ? "
p2: .asciiz " Please enter the second number? "
ans1: .asciiz " \nYou entered a greater than b "
ans2: .asciiz " \nYou entered a equal to b "
ans3: .asciiz " \nYou entered a less than b "
.text
.globl main
main:
li $v0, 4 #system call code for print_str
la $a0, p1 #address of string to print
syscall #print the first prompt
li $v0, 5 #system call code for read_int
syscall #read first integer
move $t1, $v0 #store it till later
li $v0, 4 #system call code for print_str
la $a0, p2 #address of string to print
syscall #prints the second prompt
li $v0, 5 #system call code for read_int
syscall #read first integer
move $t2, $v0 #store it till later
slt $t1,$s1,$s0 # checks if $s0 > $s1
beq $t1,1,label1
I really don't know how to use branch statements, and it's really confusing. I would like to know how to fix it.
Why do you read the numbers into $t1 and $t2 then compare $s1 and $s0? Where is it confusing?
Simply use slt and beq/bne, that'll cover all comparison cases you need.
Suppose a is in $s0, b is in $s1
a < b:
slt $t0, $s0, $s1
bne $t0, $zero, a_lt_b # $t0 == 1 != 0 if a < b
a = b:
beq $s0, $s1, a_eq_b # nothing more to explain
a > b:
slt $t0, $s1, $s0
bne $t0, $zero, b_lt_a # $t0 == 1 != 0 if b < a
a >= b:
slt $t0, $s0, $s1
beq $t0, $zero, a_ge_b # $t0 == 0 if a >= b or !(a < b)
a <= b:
slt $t0, $s1, $s0
beq $t0, $zero, b_ge_a # $t0 == 0 if b >= a or !(b < a)

Translate C++ to MIPS Assembly

I need help with this last part of this problem. I'm basically trying to translate C++ code into MIPS Assembly language.
Assume a is in $s0, b in $s1, c in $s2, x in $s4, y in $s5, and z in $s6.
I finished almost all of them but I am stuck on these two, I know some parts of it but I'm having trouble putting it together as a whole. The parts I know will be followed by hashtags with the assembly code. Thanks for any help.
1.
for(x = 0; x <= z; x++) # x = 0; is: addi $s4, $0, 0
y = y + 1; # addi $s5, $s5, 1
y = 0; # addi $s5, $0, 0
2.
if(y > z)
x = 0; # addi $s4, $0, 0
else x = 1; # else: addi $s4, $0, 1
Here are the oringinal problems without the hashtags incase I am wrong:
1.
for(x = 0; x <= z; x++)
y = y + 1;
y = 0;
2.
if(y > z)
x = 0;
else x = 1;
Thanks again.
Attempt at 2, not sure if right.
ifLoop:
add $s5, ? , $s6
addi $s4, $0, 0
ifLoop
else:
addi $s4, $0, 1
else
Practice: (Assume array p is in $s7)
p[0] = 0;
int a = 2;
p[1] = a;
p[a] = a;
My attempt:
sw $0, 0($s7)
addiu $s0, $0, 2
sw $s0, 4($s7)
sll $t0, $s0, 2
addu $t1, $t0, $s7
sw $s0, 0($t1)
Edit: 1. Luckily it is not much different without pseudo instructions.
addi $s4, $0, 0
forLoop: sle $t1, $s4, $s6 #if x <= z, set $t1 to 1, else 0
addi $s5, $s5, 1
addi $s5, $0, 0
addi $s4, $s4 1
bne $t1, $0, forLoop #repeat loop while $t1 is not 0
Here is #2. I just wanted for you to give it a go before I just gave the answer. You want to use the slt instruction to set a register to 1 or 0. If 1, the comparison is true (y > z). Then use bne to determine where to jump to. By comparing the bne to 0, the true code ends up being directly below the bne instruction. For the else, jump to the label.
slt $t2, $s6, $s5 # if z < y, set $t2 to 1, else 0
bne $t2, $0, else # if $t2==1, do the code below, if not, go to else
addi $s4, $0, 0
j continue # need the jump instruction to skip the else below
else:
addi $s4, $0, 1
continue:
# rest of code/program

C++ code into MIPS, the code in MIPS runs without error messages, but does not display results

The assignment asked us to complete a code in MIPS. The initial MIPS code needed a function we had to translate from a C++ code. I translated the function from C++ to MIPS as required.
The code in MIPS does not display any errors when I run it. However, the code does not display anything.
I tried to debug it, but I still don't see where the problem is. I am using Notepad++ as an editor and QtSpim to run the MIPS code. I posted the code(in C++ first, then in MIPS) bellow. Your help will be appreciated.
//*************C++ Code***********************
#include <stdio.h>
void update(float *, float *);
int main()
{
float x[5] = {.1, .2, .4, .6, .85};
float vx[5] = {-.2, -.15, .05, -.2, .2};
int i, steps;
for (i=0; i<5; i++)
{
printf("%d %f %f\n", i, x[i], vx[i]);
}
for (steps=0; steps<3; steps++)
{
update(x, vx);
printf("Step %d\n", steps);
for (i=0; i<5; i++)
{
printf("%d %f %f\n", i, x[i], vx[i]);
}
}
}
void update(float pos[], float vel[])
{
int i;
for (i=0; i<5; i++)
{
pos[i] += vel[i];
if (pos[i] < 0.)
{
pos[i] = 0.;
vel[i] = - vel[i];
}
else if (pos[i] > 1.)
{
pos[i] = 1.;
vel[i] = - vel[i];
}
}
}
//************************End of C++ Code*************************
//**************************Code Translated in MIPS*************
.data
x: .float 0.1
.float 0.2
.float 0.4
.float 0.6
.float 0.85
vx: .float -0.2
.float -0.15
.float 0.05
.float -0.2
.float 0.2
zero: .float 0.
one: .float 1.
space: .asciiz " "
endl: .asciiz "\n"
outStep:.asciiz "Step "
# i $s0
# steps $s1
# &x[0] $s2
# &vx[0] $s3
.globl for
.text
main: la $s2, x
la $s3, vx
move $t2, $s2
move $t3, $s3
li $s0, 0 # for (i=0; i<5; i++) {
ploop: move $a0, $s0 # printf("%d %f %f\n", i, x[i], vx[i]);
li $v0, 1
syscall
la $a0, space
li $v0, 4
syscall
l.s $f12, ($t2)
li $v0, 2
syscall
la $a0, space
li $v0, 4
syscall
l.s $f12, ($t3)
li $v0, 2
syscall
la $a0, endl
li $v0, 4
syscall
addi $t2, $t2, 4
addi $t3, $t3, 4
addi $s0, $s0, 1 # }
blt $s0, 5, ploop
li $s1, 0 # for (steps=0; steps<3; steps++) {
loop: move $a0, $s2 # update(x, vx);
move $a1, $s3
jal update
la $a0, outStep # printf("Step %d\n", steps);
li $v0, 4
syscall
move $a0, $s1
li $v0, 1
syscall
la $a0, endl
li $v0, 4
syscall
move $t2, $s2
move $t3, $s3
li $s0, 0 # for (i=0; i<5; i++) {
ploop1: move $a0, $s0 # printf("%d %f %f\n", i, x[i], vx[i]);
li $v0, 1
syscall
la $a0, space
li $v0, 4
syscall
l.s $f12, ($t2)
li $v0, 2
syscall
la $a0, space
li $v0, 4
syscall
l.s $f12, ($t3)
li $v0, 2
syscall
la $a0, endl
li $v0, 4
syscall
addi $t2, $t2, 4
addi $t3, $t3, 4
addi $s0, $s0, 1
blt $s0, 5, ploop1
addi $s1, $s1, 1
blt $s1, 3, loop
li $v0, 10
syscall
# void update(float pos[], float vel[]) {
# arg0 $a0
# arg1 $a1
# i $s0
update: l.s $f30, zero
l.s $f31, one
# The function i translated in MIPS is right bellow
addi $s0,$s0,0 # i=0
add.s $f0, $f0, $f1 # pos[i] += vel[i];
c.lt.s $f0, $f30 # if (pos[i] < 0.) {
bc1f else
add.s $f0, $f0, $f30 # pos[i]=0;
sub.s $f1, $f30 , $f1
sub.s $f31, $f30, $f31
add.s $f1, $f1, $f31 # vel[i] = - vel[i];
blt $s0, 5, update
else : c.lt.s $f31, $f0 #else if (pos[i] > 1.) {
bc1f skip
add.s $f0, $f0, $f31
sub.s $f31, $f30, $f31
sub.s $f1, $f1, $f31
blt $s0, 5, update
skip : add $s0, $s0, 0
addi $s0, $s0, 1
slti $t1, $s0, 5
blt $s0, 5, update
end: jr $31 #}
I tried it in PCSpim, but changed .globl for to .globl main. Now there is output, but your update function doesn't work yet as expected. You use $f0 and $f1, but these are never loaded or stored, so there is no update.