4

I am trying to call a function declared in a C file from an assembly file, but I am getting a "Illegal Instruction" error.

My C code:

#include <stdio.h>

int BubbleSort(int *v){
    return 13;
}

int Run(int *, int *);


int main(){
    int vetor[] = {1, 3, 5, 4, 10}, numTrocas = 0, res = 0;
    numTrocas = Run(vetor, &res);   
    printf("numTrocas= %d\nf= %d\n", numTrocas, res);
    return 0;
}

My Assembly code:

.data 
.text 
.globl Run

Run:
    addi $sp,$sp,-8
    sw $ra,0($sp)
    sw $a0,4($sp)
    move $t4, $a1 #$t4 = $a1; address of variable res in C file
    move $t6, $a0 #$t6 = address of the first vector element

    lw $a0, ($t6)
    add $t6, $t6, 4
    lw $a1, ($t6)
    add $t6, $t6, 4
    lw $a2, ($t6)
    add $t6, $t6, 4
    lw $a3, ($t6)
    add $t6, $t6, 4
    lw $t3, ($t6)
    jal PolyCalc

    lw $a0,4($sp)
    jal BubbleSort #-> Illegal Instruction

    lw $ra, 0($sp)
    addi $sp, $sp, 8 
    jr $ra

PolyCalc: #This function calculates the result of the expression 5(V[0] + V[1])(V[2] − 3xV[3]xV[4])
    li $s0,5             #$s0 = 5
    li $s1,3             #$s1 = 3
    add $t1,$a0,$a1      #t1=(x1+x2)
    mul $t1,$t1,$s0      #t1=5*(x1+x2)
    mul $t2,$a3,$t3      #$t2 = x4*x5
    mul $t2,$t2,$s1      #$t2 = 3*x4*x5
    sub $t2,$a2,$t2      #$t2 = (x3-3x4*x5)
    mul $t1,$t1,$t2      
    sw $t1, ($t4) #Save the result on the address of $t4
    jr $ra

When I comment the line jal BubbleSort and add a random value to $v0 as a return of the BubbleSort function I stop getting that error and the program works fine.

Can someone find the error in my code? Thanks

Daniel Oliveira
  • 1,280
  • 14
  • 36
  • How do you compile and link this? Have you stepped through the program in a debugger? – Michael May 02 '16 at 11:16
  • Normally illegal instruction error can occur because the program will have bug which will make it jumps in a random address with plain data or in code but not in the start of the opcode. Incase it is a manually written code assembly code then i would like you to check the stack return to ensure it is not pointing the right value. – shri May 02 '16 at 11:24
  • 2
    Oops, I mixed up caller-saved and callee-saved sorry. I meant **callee**-saved, meaning you must preserve `$s0` and `$s1` for your caller and `PolyCalc` doesn't do that which in turn means `Run` doesn't either and the C calling code might be unhappy about it later. But that's not the cause of the illegal instruction. (Deleted older comments) – Jester May 02 '16 at 11:26

2 Answers2

2

For good measure, in your asm file, you should probably add:

.extern BubbleSort

Then, the jal BubbleSort should get relocated correctly.

But, the linker may place it too far away for the [limited] range of jal, so you may have to replace it with:

la $t0,BubbleSort
jalr $t0
Craig Estey
  • 30,627
  • 4
  • 24
  • 48
-1

The error you are experiencing is because the assembly code is not able to find the label called BubbleSort to jump. I think you should be using a different approach. You can embed assembly code in C using the asm function.

Something like:

#include <stdio.h>

int BubbleSort(int *v){
    asm("lw $a0, ($t6)"
    "lw $a1, ($t6)");
}

int Run(int *, int *);


int main(){
    int vetor[] = {1, 3, 5, 4, 10}, numTrocas = 0, res = 0;
    numTrocas = Run(vetor, &res);   
    printf("numTrocas= %d\nf= %d\n", numTrocas, res);
    return 0;
}

You can find more information about this function in the GCC documentation: https://gcc.gnu.org/onlinedocs/gcc/Extended-Asm.html

  • Wouldn't linking fail if this was the case? – Ctx May 02 '16 at 12:20
  • GNU C inline asm does *not* make things simpler or easier. You have to understand a lot more stuff to write correct constraints that are safe under all conditions. It's easy to write inline asm that appears to work (esp. if you only test without optimization), but then breaks after you change the C or compile options. See http://stackoverflow.com/questions/34520013/using-base-pointer-register-in-c-inline-asm/34522750#34522750 for more on that. Your asm is completely bogus, and only maybe works if you used `__attribute__((noinline))` on the function you put it in – Peter Cordes May 03 '16 at 05:31