MIPS Error : Cannot write directly to text segment!0x00500000 - bubble-sort

I'm trying to do a mips interactive exercise (BubbleSort). I have to read 20 integers from the user and store them into an array,then sort the array with the method of BUBBLESORT.
I have a problem with storing the integers into the array.
Here is a bit of my code:
.data
prompt:.asciiz "enter the integer one by one \n "
.text
addi $sp,$sp,-88 #space on the stack
lui $s0, 0x0040 #s0=adress of array
sw $s0,-84($sp) #store s0 on the stack
sw $ra,-80($sp) #store ra on the stack
readInt:
#prompt the user
li $v0, 4 #op code to print string
la $a0, prompt
syscall
#get the array's integer
addi $t0,$zero,0 #t0=compteur
addi $a1,$zero,80 #a1=size of array*4 (20 int)
move $a0,$s0 #a0= adress of array
loop:
beq $t0,$a1,BubbleSort #if t0 = size of array ==>BubbleSort
li $v0,5 #opcode to read int
syscall
**sw $v0,0($a0)** ERROR HERE !!!! :(
addi $a0,$a0,4 #increment a0 (next int)
addi $t0,$t0,4 #incrementer t0 (counter +=4)
j loop

Related

Jumping to various functions MIPS

So I am new to MIPS and I wanted to implement simple modulo arithmetic functions. I am unable to see why the program is not jumping according to the jump statements in the code. Any help would be appreciated.
.data
text_enquiry : .asciiz "Enter operation code (1-add, 2-subtract, 3-multiply, 4-exponentiation, 5-inversion, 6-exit): "
text_a : .asciiz "Enter a: "
text_b : .asciiz "Enter b: "
text_m : .asciiz "Enter m: "
text_result : .asciiz "Result = "
new_line : .asciiz "\n"
.text
main:
## t0 = code, t1 = a, t2 = b, t3 = m
#print operation message
la $a0, text_enquiry
li $v0, 4
syscall
#read code
li $v0, 5
syscall
move $t0, $v0
#if code == 6
beq $t0, 6, exit
j rest
exit:
li $v0, 10
syscall
#else, continue procedure
#print 'a, b, m' messages and read them
rest:
la $a1, text_a
li $v0, 4
syscall
li $v0, 5
syscall
move $t1, $v0
la $a1, text_b
li $v0, 4
syscall
li $v0, 5
syscall
move $t2, $v0
la $a1, text_m
li $v0, 4
syscall
li $v0, 5
syscall
move $t3, $v0
j mod
## t0 = code, t1 = a, t2 = b, t3 = m, t4 = un-modded result, t5 = modded result, t6 =
mod:
beq $t0, 1, func_add
beq $t0, 2, func_sub
beq $t0, 3, func_mul
# beq $t0, 4, func_exp
func_add:
add $t4, $t1, $t2
div $t4, $t3
mfhi $t5
#print accordingly
la $a3, text_result
li $v0, 4
syscall
move $a3, $t5
li $v0, 1
syscall
la $a3, new_line
li $v0, 4
syscall
j main
func_sub:
sub $t4, $t1, $t2
div $t4, $t3
mfhi $t5
#print accordingly
la $a3, text_result
li $v0, 4
syscall
move $a3, $t5
li $v0, 1
syscall
j main
func_mul:
mult $t1, $t2
mflo $t4
div $t4, $t3
mfhi $t5
#print accordingly
la $a3, text_result
li $v0, 4
syscall
move $a3, $t5
li $v0, 1
syscall
j main
As you can see, the code works fine when the code is '6' but doesn't work for any other code value.
I am unable to see why the program is not jumping according to the jump statements in the code. Any help would be appreciated.
Your program is jumping according to the input.
What you are unable to see is what it really does and why your further text output fails, and you are unable to see that, because you didn't even look (in debugger, single-stepping over every instruction).
Would you take a look, you would clearly see that for example for input "3", the code will reach instruction after label rest:, so the branching is correct.
That code later is not doing what you expect, because it doesn't print the other helper prompts, because it is calling syscall with wrong arguments (the code sets a1 with string address, instead of a0, and in a0 is still the original operation-prompt address), but it is executed as planned.
Generally deciding on assembly code correctness only by checking input/output is very bad practice, as you can often have correct output "by accident", while the code is already doing also something different than planned, which may just bite you later, if you keep extending your code, or if you use different inputs.
To decide if your assembly code is correct, you should rather spend quite some time in debugger, verifying different inputs, and thinking how the code works and if really works as planned/assumed, while you were writing it - on per-instruction basis!
The final code should consist only of instructions which you know exactly what they are doing, and why they are part of the code, and why they are placed where they are. If anything works "by accident" without you truly understand it, you must fix it (either by understanding how it works, or by rewriting it in a way you understand how it works), it's still bug, even if the output is correct.

MIPS Assembly, setting array[index - i] = IntReturnFunction(argument)

I am new to using the stack and functions in MIPS, for an assignment we are translating a c++ program into MIPS in order to learn how functions work. My problem is translating this c++ code into MIPS, intArr[valsToDo - i] = GetOneIntByVal(entIntPrompt);.
I will show what I have so far but keep getting address out of range error.
# intArr[valsToDo - i] = GetOneIntByVal(entIntPrompt);
addi $a0, $sp, 41
jal GetOneIntByVal
sw $v0, 41($sp)
lw $a1, 77($sp)
sub $a3, $t1, $t1 #$a3 has valsToDo - i
sll $a3, $a3, 2 #$a3 has (valsToDo - i) * 4
add $a3, $a3, $a1 #$a3 has &intArr[valsToDo - i]
lw $a2, 0($a3) #$a2 has intArr[valsToDo - i]
What am I doing wrong?

Converting C++ Palindrome function to MIPS

I'm trying to convert a function I wrote in C++ into MIPS. The function tests whether a char array is a palindrome, a string that is symmetric in its characters (ex: "heeh" and "gtrertg" are palindromes, "hey" is not). In MIPS, the string is being passed through $a0 and the return value should be passed in $v0. This is my C++ code:
#include <iostream>
using namespace std;
int palindrome(char s[])
{
int j;
j = 0;
int i;
i = -1;
//finding length of string...
while(s[i+1] != '\0')
{
i++;
}
//while the two opposite chars are equal...
while(s[j] == s[i])
{
//if the chars are at the same index...
if(i == j)
{
//palindrome
return 1;
}
//if the left index passes the right index...
if(j > i)
{
//palindrome
return 1;
}
//increment left index
j++;
//decrement right index
i--;
}
//not palindrome
return 0;
}
I have tested my C++ code and it works just fine. This is my MIPS code:
#$a0 contains the address of the string
.data
.text
.globl palindrome
palindrome:
li $t0, 0 #j = 0
li $t1, -1 #i = -1
addi $t2, $a0, 0 #a[0]
L1:
addi $t2, $t2, 1 #a[i + 1]
addi $t1, $t1, 1 #i++
bne $t2, $zero, L1 #exit loop when '\0' is found
add $t2, $a0, $t0 #a[j]
add $t3, $a0, $t1 #a[i]
L2A:
bne $t1, $t0, If2 #if i does not equal j jump to next if
j Return1 #jump to Return1 label
If2:
ble $t1, $t0, L2B #if j<= i, skip if statement
j Return1 #jump to Return1 label
L2B:
addi $t0, $t0, 1 #j++
addi $t1, $t1, -1 #i--
beq $t2, $t3, L2A #exit loop when a[j] != a[i]
Return1:
addi $v0, $zero, 1 #return 1
j Exit
Return0:
addi $v0, $zero, 0 #return 0
j Exit
Exit:
jr $ra #return
I'm getting an error in my first loop when determining the size of the string when checking for the \0 character. Can someone help? Also, I have to convert the characters of the string into the same case. Would I need another loop in the beginning to go and check for their int ASCII representation and increment or decrement it by a certain number depending on the case? If you see any other mistakes, including conventional mistakes, please point them out. The file that tests the palindrome file has been error checked and works as it should.

From C++ to MIPS - Structs [duplicate]

typedef struct node {
int data;
struct node *next;
} nodeL;
Assuming I want to translate the above declaration in MIPS assembly language, how am I supposed to do it? Apart from allocating memory (using syscall 9), which is done in the .text segment, what about the .data segment?
Also, what about alignment?
Before even mentioning code, you need to clarify whether the struct you want to create will be static data (data segment), local data (stack), or dynamically allocated data (heap). There are different ways to allocate each.
But before discussing that, the very first thing you need to do is determine the layout of the struct instance. At the very least it could be:
------------------
| data - 32-bits |
------------------
| next - 32-bits |
------------------
To create an instance statically, it's simply:
.data
.align 2
anInstance: .word 0,0
And on the heap:
.text
Allocator.newNode:
li $a0, 8 #allocate 8 bytes
li $v0, 9
syscall #returns word-aligned ptr
jr $ra
If placing on the stack, simply allocate 8 bytes for it.
A cleaner way is to use a prototype-based method.
Your object layout becomes:
------------------
| size - 32-bits |
------------------
| atr 1 - 32-bits|
------------------
| atr 2 - 32-bits|
------------------
.
.
.
------------------
| atr n - 32-bits|
------------------
For each struct, you create a prototype which the allocation routine will use to create the instance.
.data
ListProto: .word 8,0 #size, head ptr
NodeProto: .word 12,0,0 #size, data, next ptr
.text
main:
la $a0, ListProto
jal Allocator.newObject #create new list instance
la $a0, NodeProto
jal Allocator.newObject #create new node instance
Allocator.newObject:
lw $a0, 0($a0) #a0 = object size
li $v0, 9
syscall
jr $ra
Whether you want the instance to actually keep a size field is up to you. With that approach you can simply add prototypes and that's it.

converting C code to MIPS problems with recursion and multiplication

hello everyone i need some help converting the following C code into MIPS:
main()
{
int i;
for (i=0;i<5;++i)
power(2,1)
factorial(i)
return 0;
}
int power(int base,int n)
{
int i,p;
p=0;
for(i=1;i<=n;++i)
p=p*base;
return p;
}
int factorial(int a)
{
if(a==1)
return 1;
else
{
a *=factorial(a-1);
return a;
}
}
i have only done the factorial part so far but i'm stuck at a*=factorial(a-1), i under stand that multi is used to multiply two registers together but how can it take the input of a recursive loop? also is it possible to multi to multiply with a constant instead of another register?
factorial:
addi $sp, $sp, -8 #adjust stack for 2 items
sw $ra, 4($sp) #save return address
sw $a0, 0($sp) #save argument
bne $a0, 1, Else #if !(a==1), go to else address
addi $v0, $zero, 1 #result is 1
addi $sp, $sp, 8 #pop 2 items from stack
jr $ra #return
Else: addi $a0, $a0, -1 #decrement s-1
jal factorial #recursive call
lw $a0, 0($sp) #restore original a
lw $ra, 4($sp) #and return address
addi $sp, $sp, 8 #pop two items from stack
Here is a code that I wrote, I think it will fit your purpose.
.text
factorial:
li $t0,13 # load 13 to check for overflow
blt $a0,$t0,no
li $v1,1
no:
bgtz $a0,find # if $a0>0 goto generic case
li $v0, 1 # base case, 0! = 1
jr $ra
find: sub $sp,8 # make room for $s0 and $ra
sw $s0,($sp) # store argument $s0=n
sw $ra,4($sp) # store return address
move $s0, $a0 # save argument
sub $a0, 1 # factorial(n-1)
jal factorial # v0 = (n-1)!
mul $v0,$s0,$v0 # n*(n-1)!
lw $s0,($sp) # restore $s0=n
lw $ra,4($sp) # restore $ra
add $sp,8 # reduce stack size
jr $ra # return
main:
la $a0,input
li $v0,4
syscall
li $v0,5
syscall
move $a0,$v0
jal factorial
move $t0,$v1
bnez $t0,overflow1
move $a0,$v0
li $v0,1
syscall
b end
overflow1:
la $a0,overflow
li $v0,4
syscall
end:
li $v0,10
syscall
.data
input:.asciiz"Input a number:"
overflow:.asciiz"There is an overflow!!"
It's complete with comments and explanations so there shouldn't be problems.