Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to use C defines in ARM assembler

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.

like image 932
Sint Avatar asked Jun 19 '10 15:06

Sint


3 Answers

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 #defineitions), 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.

like image 72
James Avatar answered Nov 08 '22 02:11

James


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.

like image 26
ShinTakezou Avatar answered Nov 08 '22 02:11

ShinTakezou


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.

like image 33
Sint Avatar answered Nov 08 '22 02:11

Sint