I have these two files, 9-main.c and 9-mult.s.
9-main.c :
#include <stdio.h>
int mult(int);
int main(){
int result = mult(5);
printf("Result: %d\n",result);
return 0;
}
9-mult.s :
.global mult
mult:
mov r1,r0
lsl r0,r0,#4
add r0,r1,r0
bx lr
I am trying to link them:
$ arm-linux-gnueabihf-gcc 9-main.c 9-mult.s
But if I execute a.out:
$ ./a.out
Illegal instruction
What could be the reason?
You are compiling/executing in a non-trivial environment for a beginner: compiling/linking/executing a mix of
aarch32
C/assembly code on aaarch64
system.I would suggest to start specifying which architecture you are assembling for as well as the exact instruction set you are using - this is useful information for people who want to help - and to use some standard directives for defining functions in GNU AS assembly language, the way they would be generated by the gcc compiler:
Please refer to the GNU AS documentation for more details.
I am still looking for the root cause of your problem, which was actually fixed by using
.type mult, %function
. Note that the exact same error does occur on aCortex-A7
Linux system, that is the fact that use are running a 64 bit Linux is not the issue.Compiling two executables (with/without the .type directive) and comparing the outputs of the
readelf -a
command shows only one difference:UPDATE:
The reason for your problem was pointed-out by old_timer - see his comment hereafter.
Your compiler is generating thumb2/T32 code by default, but your assembly code was arm/A32 by default since you did not specify which instruction set you where using. Compiling you original code with gcc
-marm
option (arm/A32) works fine:The other option would be to force GNU AS to generate thumb2/T32 code in mult.s:
For more details on thumb2/T32, arm/A32 and interwork code, see here and here.