Translate C++ to MIPS Assembly - c++

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

Related

QUICKSORT IN MIPS

I have written a quicksort algorrithm in MIPS assembly according to C++ code. In C++, it works very well but in MIPS, it doesn't work. I debugged it, and problem is recursion. This is the algorithm:
QuickSort(Data[], l , r)
{
// If the first index less or equal than the last index
if l <= r:
{
// Create a Key/Pivot Element
key = Data[r]
// Create temp Variables to loop through array
i = l;
j = r;
while i <= j:
{
while Data[i] < key AND i < r:
i = i + 1
while Data[j] > key AND j > 0:
j = j - 1
if i <= j:
{
swap Data[i], Data[j]
i = i + 1
j = j + 1
}
}
if l < j:
QuickSort(Data, l, j);
if r > i:
QuickSort(Data, i, r);
}
}
This is MIPS code. It works in some cases. ex: array = {6, 5, 4, 3, 2, 1}.
MIPS code:
#-function QuickSort(arr, left,right)
#parameter
# $a0: array
# $a1: left
# $a2: right
QuickSort:
subu $sp, $sp, 16
sw $a0, 0($sp)
sw $a1, 4($sp)
sw $a2, 8($sp)
sw $ra, 12($sp)
la $s0, 0($a0)
move $s1, $a1
move $s2, $a2
bgt $s1, $s2, done
sll $t3, $s2, 2
add $t3, $s0,$t3
lw $t2, 0($t3)
move $t0, $s1
move $t1, $s2
WhileOuter:
While_i:
sll $t3, $t0, 2
add $t3, $s0, $t3
lw $t4, 0($t3)
bge $t4, $t2, EndWhile_i
bge $t0, $s2, EndWhile_i
addi $t0, $t0, 1
j While_i
EndWhile_i:
While_j:
sll $t3, $t1, 2
add $t3, $s0, $t3
lw $t4, 0($t3)
ble $t4, $t2, EndWhile_j
blez $t1, EndWhile_j
addi $t1, $t1, -1
j While_j
EndWhile_j:
bgt $t0, $t1, EndWhileOuter
#swap arr[i], arr[j]
sll $t4, $t0, 2
sll $t5, $t1, 2
add $s3, $s0, $t4
add $s4, $s0, $t5
lw $t4, 0($s3)
lw $t5, 0($s4)
sw $t4, 0($s4)
sw $t5, 0($s3)
addi $t0, $t0, 1
addi $t1, $t1, -1
j WhileOuter
EndWhileOuter:
bge $s1, $t1, call2
lw $a1, 4($sp)
move $a2, $t1
move $a0, $s0
jal QuickSort
call2:
ble $s2, $t0, done
move $a1, $t0
lw $a2, 8($sp)
move $a0, $s0
jal QuickSort
done:
addu $sp, $sp, 16
lw $a0, 0($sp)
lw $a1, 4($sp)
lw $a2, 8($sp)
lw $ra, 12($sp)
jr $ra
Can anyone find the error(s) in this code? Thanks for any help.
You are using the saved registers $s0, $s1, $s2, but without following the requirement to preserve the values in those registers for the caller.
Thus, the callers of QuickSort are not guaranteed their $s registers will be preserved.
You aren't showing the rest of the code, e.g. the main.
However, we know that QuickSort calls itself, and, after the first recursive call to itself, it relies on the $s0 & $s2 registers, which should be ok, but we know they aren't properly preserved by QuickSort.
You need to more closely analyze your register usage and requirements. The following code runs after the first (recursive) call to QuickSort. It rightfully expects $s0 and $s2 to be preserved, but also expects $t0 to be preserved — which is a temporary register meaning it is not preserved by a call, so this is an error.
jal QuickSort # this call wipes out $t0
call2:
ble $s2, $t0, done # what's supposed to be in $t0 here?
move $a1, $t0
lw $a2, 8($sp)
move $a0, $s0
You have no requirement for saved register $s1 and should have chosen a temporary register for that usage instead. I would have just used the variable in its original $a1 register.
You're saving $a0 register to memory but not using that memory location's value.
It is either missing or you've changed the location of the outer while loop's exit condition. It is no longer at the top of the loop. It now reads like this:
while true:
{
while Data[i] < key AND i < r:
i = i + 1
while Data[j] > key AND j > 0:
j = j - 1
if i > j break;
The Python code does
if i <= j:
{
swap Data[i], Data[j]
i = i + 1
j = j + 1
}
whereas after the swap the assembly code does i++ yet j-- .
You're using $s3 and $s4 but for simple temporary usages — use $t registers for these purposes instead.

Mips code with PCspim exception 7

i have written a code that permutes a string in all its possible ways. The original code is in C++, and the task of the exercise is to implement the code in C++ in MIPS.For example, if you insert "abc" the result is [abc,acb,bca,bac,cba,cab]. So in C++ looks like this:
void Permutaciones(char * cad, int l) {
char c;
int i, j;
int n = strlen(cad);
for(i = 0; i < n-l; i++) {
if(n-l > 2) Permutaciones(cad, l+1);
else cout << cad << ", ";
c = cad[l];
cad[l] = cad[l+i+1];
cad[l+i+1] = c;
if(l+i == n-1) {
for(j = l; j < n; j++) cad[j] = cad[j+1];
cad[n] = 0;
}
}
}
and here's my code in MIPS
.data
str: .asciiz "abc"
coma: .asciiz ", "
.text
main:
la $a0, str
li $a1, 0
jal perm
li $v0, 10
syscall
length:
lb $t0, 0($a0)
beq $t0, $0, preperm
addi $v0, $v0, 1
addi $a0, $a0, 1
j length
preperm:
subu $a0, $a0, $v0
jr $ra
perm:
subu $sp, $sp, 32
sw $ra, 0($sp) #salvo ra
sw $a0, 4($sp) #salvo cad
sw $a1, 8($sp) #salvo L
jal length
sw $v0, 12($sp) #salvo n
subu $v0, $v0, $v0
lw $a0, 4($sp) #rescato cad
lw $a1, 8($sp) #rescato L
lw $t0, 12($sp) #rescato n
li $t2, 0 #$t2=i=0
for1:
sub $t1, $t0, $a1 # $t1= n- L
bge $t2, $t1, fin1 # i >= n- L => fin1
li $t3, 2 # $t3=2 (constante)
bgt $t1, $t3, recursion #n-L >2 => recursion
mostrar:
li $v0, 4
syscall
la $a0, coma
syscall
subu $v0, $v0, $v0
jal nomostrar
recursion:
sw $t2, 16($sp) #salvo i
addi $a1, $a1, 1 #l++
jal perm #recurso
nomostrar:
lw $a0, 4($sp) #rescato cad
lw $a1, 8($sp) #rescato L
lw $t0, 12($sp) #rescato n
lw $t2, 16($sp) #rescato i
add $t4, $a0, $a1 #$t4 = direccion cad[L]
lb $t5, 0($t4) #$t5=cad[L]
add $t6, $a0, $a1
add $t6, $t6, $t2
addi $t6, $t6, 1 #$t6=direccion cad [L+i+1]
lb $t7, 0($t6) #$t7 = cad [L+i+1]
sb $t7, 0($t4)
sb $t5, 0($t6) #swap (cad[L],cad [L+i+1])
add $t7, $a1, $t2 #$t7 = L+i
subu $t5, $t0, 1 #$t5 = n-1
bne $t7, $t5, cola #L+i != n-1 => cola
or $t8, $a1, $0 #t8= j = L
for2:
bge $t8, $t0, cola # j >= n => cola
add $t5, $a0, $t8 #$t5 = dirección de cad[j]
addi $t1, $t5,1 #$t1 = dirección de cad[j+1]
lb $t7, 0($t1) #$t7 = cad[j+1] propiamente dicho
sb $t7, 0($t5) # cad[ j ] = cad[j+1]
addi $t8, $t8, 1 # j++
j for2 # repetir
cola:
add $t8, $a0, $t0 #$t8 = dirección de cad[n]
sb $0, 0($t8) # cad[n] = '\0'
addi $t2, $t2, 1 # i++
sw $t2, 16($sp)
j for1 # repetir
fin1:
lw $ra, 0($sp) #rescato ra
sw $0, 16($sp)
addi $sp, $sp,32 #libero memoria
jr $ra #retorno
So, the problem is that when i run the program in PCspim using F5 i get the first output "abc" then i get Exception 7 Bad data address two times, and then it shows some more letters of the string. But when I use the step by step function (F10), the code works perfectly. Please someone help me, because i`m losing my mind.

Branching in mips

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:

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)

MIPS : loop goes to infinity

I am trying to convert this c++ function to mips. I think I am having problem in loop because when I run it, it gives me 13..1.17.5.. but my output should be two ip addresses : 130.52.0.10 and 171.9.50.186
C++ function code :
void IPtoDD(int arg0, char *arg1)
{
int temp, numChar, shift = 24;
for (int i=0; i<4; i++) {
temp = arg0 >> shift;
temp = temp & 0x000000ff;
numChar = byteToDec(temp,arg1);
arg1 += numChar;
*arg1++ = '.';
shift -= 8;
}
arg1--;
*arg1 = 0;
return;
}
MIPS code :
IPtoDD: addi $sp, $sp, -20
sw $ra, ($sp)
sw $s0, 4($sp)
sw $s1, 8($sp)
sw $s2, 12($sp)
sw $s3, 16($sp)
move $s0, $a0
move $s1, $a1
li $s3, 24 #s3=shift
li $s2, 0 #s2=i
li $t5, 0 #t5=temp
li $t3, 0
move $s1, $a1 #s1=*arg1
loop: srl $t5, $s0, $s3 #t3= numChar
and $t5, $t5, 0xff #t4= (*arg1)
move $a0, $t5
move $a1, $s1
jal byteToDec
move $t3, $v0
add $s1, $s1, $t3
li $t5, '.'
sb $t5, ($a1)
addi $a1, $a1, 1
addi $s3, $s3, -8
addi $s2, $s2, 1
blt $s2, 4, loop
addi $s1, $s1, -1
sb $0, ($a1)
lw $s3, 16($sp)
ra: lw $s2, 12($sp)
lw $s1, 8($sp)
lw $s0, 4($sp)
lw $ra, ($sp)
addi $sp, $sp, 20
jr $ra
Could please help out here. I tried a lot but not able make it run correctly.
edit:
C++ function for byteToDec
int byteToDec(int arg0, char *arg1)
{
int temp, flag = 0, count = 0;
if (arg0==0) {
*arg1 = '0';
return 1;
}
else {
temp = arg0/100;
if (temp != 0) {
*arg1++ = (char) temp + 0x30;
count++;
flag = 1;
}
temp = (arg0 % 100) / 10;
if ((flag!=0) || (temp != 0)) {
*arg1++ = (char) temp + 0x30;
count++;
}
temp = arg0 % 10;
*arg1 = (char) temp + 0x30;
count++;
return count;
}
}
byteToDec in MIPS:
byteToDec: #t0= temp
#t1= flag
#v0= count
#t3= (*arg1)
bne $a0, $0, else
li $t3, '0'
sb $t3, ($a1)
li $v0, 1
jr $ra
else: div $t0, $a0, 100
beq $t0, 0, cont
bp2: addi $t3, $t0, 0x30
sb $t3, ($a1)
addi $a1, $a1, 1
addi $v0, $v0, 1
li $t1, 1
cont: rem $t3, $a0, 100
div $t0, $t3, 10
bne $t1, 0, nxtIf
beq $t0, 0, endElse
nxtIf: addi $t3, $t0, 0x30
sb $t3, ($a1)
addi $a1, $a1, 1
addi $v0, $v0, 1
endElse:rem $t0, $a0, 10
bp1: addi $t3, $t0, 0x30
sb $t3, ($a1)
addi $v0, $v0, 1
ra1: jr $ra
You are using t3 as your loop counter and then trashing t3 in your byteToDec function. MIPS convention is that t registers are "temp" and not to be used across function calls like that. You should put your loop variable in a s register (a "save" register), and if your called function needs to reuse that same s register, it needs to save it to the stack or something and restore the value before returning to the callee.
I Have a program and it the first loop works ell but the second to 6th loop goes to inf. I'm a beginner and could use some help
#include <iostream>
#include <cmath>
#include <fstream>
using namespace std;
ofstream myfile ("Atomseries.txt");
int main()
{
float rconstant=109677.58;
int nstart, nend;
int length;
for (nstart = 1; nstart <= 6; nstart++){
for (nend= 2; nend <=nstart + 10; nend++)
length = 1/(rconstant*(1/(nstart*nstart)- 1/(nend*nend)));
myfile << length * 10000000 << endl;
}
if (nstart = 1)
myfile << "Lyman Series"<< endl;
else
;
if (nstart = 2)
myfile << "B Series" << endl;
else
;
if (nstart= 3)
myfile << " series"<< endl;
return 0;
}