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.
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.
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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With