Reputation: 1620
How can I use external defines such as LONG_MIN and LONG_MAX in ARM assembler code?
Let's say my_arm.h looks like this:
int my_arm(int foo);
Let's say I have a my_main.c as follows:
...
#include <limits.h>
#include "my_arm.h"
...
int main (int argc, char *argv[])
{
int foo=0;
...
printf("My arm assembler function returns (%d)\n", my_arm(foo));
...
}
And my_arm.s looks like this:
.text
.align 2
.global my_arm
.type my_arm, %function
my_arm:
...
ADDS r1, r1, r2
BVS overflow
...
overflow:
LDR r0, LONG_MAX @ this is probably wrong, how to do it correctly?
BX lr @ return with max value
The second to last line, I am not sure how to load correctly, I vaguely remember reading somewhere, that I had to define LONG_MAX in .global, but can't find the link to a working example anymore.
I am compiling with arm-linux-gnueabi-gcc version 4.3.2
==================
UPDATE: Appreciate the suggestions! Unfortunately, I am still having trouble with syntax.
First, I made a little header file mylimits.h (for now in same dir as .S)
#define MY_LONG_MIN 0x80000000
in my_arm.S i added the following:
...
.include "mylimits.h"
...
ldr r7, =MY_LONG_MIN @ when it was working it was ldr r7, =0x80000000
...
Two problems with this approach.
First the biggest problem: the symbol MY_LONG_MIN is not recognized...so something is still not right
Second: syntax for .include does not let me include <limits.h>
, I would have to add that in mylimits.h, seems a bit kludgy, but I suppose, that is ok :)
Any pointers?
I have access to ARM System Developer’s Guide Designing and Optimizing System Software[2004] and ARM Architecture Reference Manual[2000], my target is XScale-IXP42x Family rev 2 (v5l) though.
Upvotes: 8
Views: 17879
Reputation: 25543
Often the lowercase file extension .s
implies that assembler should not be passed through the c preprocessor, whereas the uppercase extension .S
implies that it should.
It's up to your compiler to follow this convention though (gcc ports normally do), so check its documentation.
(EDIT: note that this means you can use #include directives - but remember that most of the files you would include would not normally be valid assembler (unless they consist entirely of #define
itions), so you may have to write your own header that is)
edit 5 years later:
Note that the armcc v5 compiler follows this behaviour under linux... but not on windows.
Upvotes: 11
Reputation: 15844
use --cpreproc for armasm option and add
#include "my_arm.h"
into my_arm.s.
it works for Keil ARM
Upvotes: 0
Reputation: 9671
If you are using gcc and its assembler, it is straightforward: name the file with final .S
, then add at the beginning #include <limits.h>
and use wherever you need the constant, e.g. ldr r0, SOMETHING
; I did tests with x86 since it is what I have, but the same works since it is a gcc feature.
Upvotes: 2
Reputation: 1620
What I ended up doing is this:
in my_main.c
#include <limits.h>
...
int my_LONG_MAX=LONG_MAX;
then in my_arm.S
ldr r8, =my_LONG_MAX
ldr r10, [r8]
It looks convuluted and it is(plus the portability gains are questionable in this approach).
There must be a way to access LONG_MAX directly in assembly. Such a way I would gladly accept as the full answer.
Upvotes: 1
Reputation: 71556
I have seen simply feeding gcc the assembler source vs gas will allow you to do C like things in assembler. It is actually a bit scary when you come across situations where you must use gcc as a front end to gas to get something to work, but that is another story.
Upvotes: 0