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 x5
gets 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?