Wednesday, April 18, 2012

Assembly MIPS not returning right value

I have this C code:



#include <stdio.h>

int BubbleSort(int *v);

int main()
{
int x1=4,x2=2,x3=10,x4=1,x5=6;
printf("The value of f is: %d\n", PolyCalc(x1,x2,x3,x4,x5));
return 0;
}

int BubbleSort(int *array){
int i,j,changes = 0,inPosition, size = 5;
for (i = 1; i < size; i++)
{
inPosition = 0;
for(j = 0; j < size - i; j++)
{
if(array[j] > array[j+1])
{
int temp = array[j];
array[j] = array[j+1];
array[j+1] = temp;
inPosition = 1;
changes++;
}
}
if(!inPosition){
break;
}
}
return changes;
}


This is what I want to do.



1 - Calculate PolyCalc (PolyCalc is codded in Assembly - Will post code below)



2 - From the assembly PolyCalc code, jump to the C BubbleSort function and receive the return in the assembly code



3 - On the Assembly code, print the number of changes that BubbleSort made until the array was sorted



4 - Return the PolyCalc resulting value to the C code and make the final printf.



This is my Assembly code:



01          .data
02 print: .asciiz "Where made %d changes until the array was sorted\n"
03 .text
04 .globl PolyCalc
05
06 PolyCalc:
07
08
09 lw $8, 16($29) # Goes to the stack and gets x5
10 addi $29,$29, -4 # Reserve space on the stack
11 sw $31,0($29) # Stores the ra of the caller on the stack
12
13 # Calculate this f = 2(x1+x2)(x3-3x4x5)
14
15 add $10,$4,$5 # Adds x1 and x2
16 mul $10,$10,2 # Multiply by 2 the sum of x1 and x2
17 mul $11,$7,$8 # Multiply x4 e x5
18 mul $11,$11,3 # Multiply by 3 the multiplication of x4 by x5
19 sub $11,$6,$11 # x3 minus the previous result
20 mul $10,$10,$11 # Makes the final product
21
22
23 ##### Will add some code one this space later #######
24
25
26
27
28
29
30
31
32
33
34
35
36
37 move $2, $10 # Moves the the return value
38 fim:
39
40 lw $31,0($29) # Loads the return address of the caller
41 addi $29,$29,4 # Restores stack pointer


If I compile both my main.c and prog.s I get this output



The value of f is: -96 So the first part is OK. Not only it's calculating the value as it should but also returns the value to my main.c and main.c prints the result.



Second part.
Create a print on assembly. Added this code to the previous one.



29      #Prints the number of changes on BubbleSort
30 la $4,print
31 move $5,$10
32 lw $25,%call16(printf)($28)
33 jalr $25


Running this the output is



Where made -96 changes until the array was sorted



The value of f is: 1



I can see now that the print is working ok. Although It's not printing the number of changes made on BubbleSort it´s printing the correct value that I've passed to printf.



The last printf it's not working as expected. If I change 33 jalr $25 to 33 j $25 it prints The value of f is: 50. So this is my first question:



Q1 - Why it's not returning the right value (-96) to my main.c?



Did not change nothing on my register $10 so it should return the right value...



Made this changes to the code:



10      addi    $29,$29, -8     # Reserve space on the stack
11 sw $31,4($29)
22 sw $10,0($29) # Stores on the stack the value calculated on the above lines
35 lw $10,0($29) # Restores PolyCalc value
40 lw $31,4($29)
41 addi $29,$29,8 # Restores stack pointer


And gives this:



Where made -96 changes until the array was sorted



Bus error



Made this:



10      addi    $29,$29, -8     # Reserve space on the stack
11 sw $31,0($29)
22 sw $10,4($29) # Stores on the stack the value calculated on the above lines
35 lw $10,4($29) # Restores PolyCalc value
40 lw $31,0($29)
41 addi $29,$29,8 # Restores stack pointer


Now it works but I quite understand why. The output is:



Where made -96 changes until the array was sorted



The value of f is: -96



Q2 - Why does the second solution work and not the first one?



Final step. Since the assembly code is returning the correct value to main.c and the print function is working as expected inside the assembly code, just have to call from my prog.s the BubbleSort function on main.c.



Made this:



24      la  $4,0($4)        # Stores in  `$4` the address of the first parameter 
25 j BubbleSort # Calls bublesort
26 move $14,$2 # Moves to `$14` the number of changes made
31 move $5,$14 # Print the number of changes


It gives:



Segmentation fault


Final attempt. Thought this way. Since 09 lw $8, 16($29) # Goes to the stack and gets x5gets x5 give it a try and made 08 la $15,0($29) believing that the address of the first element of the array was here. Changed 24 la $4,0($4) to 24 la $4,0($15) and running this gives:



The value of f is: 6


So no segmentation fault but still not correct.



Q3 - What am I doing wrong? How can I call bubblesort inside my assembly code?





No comments:

Post a Comment