简体   繁体   中英

How to pass a long long-typed parameter when calling c function from arm assembly?

I have a C function witch looks like:

int foo(int a, long long b);

I'm trying to call it from arm assembly, but I don't know how to deal with the second parameter( long long ).

The ARM EABI/AAPCS specifies that 64bit types should be passed in 2 registers which are next to each other and the first register must be even numbered. In little endian mode the high part resides in the higher numbered register, while the low part is put in the lowered numbered one. In big endian mode it's vice versa.

Both requirements are there to accomodate the strd/ldrd instructions, which can save two registers in a single instructions.

So, to pass 0x0123456789abcdef for your example in little endian mode you have to load the registers in the following way:

mov r0, a
// R1 is unused
ldr r2, =0x89abcdef
ldr r3, =0x01234567

(Beware: wrong answer; cannot delete it because the comments contain info)

According to the ARM ABI, the second parameter is passed in registers r1 and r2 . If your machine is little-endian, pass the low part in r1 and the high one in r2 (i don't know if this is opposite for big-endian machines). So to call the function with a parameter eg 0x123456789abcd:

MOV r0, ... (the value of "a")
MOV r1, #0x6789abcd
MOV r2, #0x12345
... (call the function)

Just ask the compiler it will tell you everything...

int foo ( int a, long long b );

int bar  ( void )
{
    return(foo(0xAABB,0x1122334455667788LL));
}

I prefer to compile then disassemble rather than compile to asm, easier to read.

arm-none-eabi-gcc -c -O2 fun.c -o fun.o
arm-none-eabi-objdump -D fun.o

fun.o:     file format elf32-littlearm


Disassembly of section .text:

00000000 <bar>:
   0:   e92d4008    push    {r3, lr}
   4:   e59f001c    ldr r0, [pc, #28]   ; 28 <bar+0x28>
   8:   e28f3010    add r3, pc, #16
   c:   e893000c    ldm r3, {r2, r3}
  10:   ebfffffe    bl  0 <foo>
  14:   e8bd4008    pop {r3, lr}
  18:   e12fff1e    bx  lr
  1c:   e1a00000    nop         ; (mov r0, r0)
  20:   55667788    strbpl  r7, [r6, #-1928]!   ; 0x788
  24:   11223344    teqne   r2, r4, asr #6
  28:   0000aabb            ; <UNDEFINED> instruction: 0x0000aabb
  2c:   e1a00000    nop         ; (mov r0, r0)

and the answer is r0 contains the first parameter, r1 skipped and r2/r3 contain the long long.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM