How do I access local C variable in arm inline assembly?

后端 未结 2 1513
生来不讨喜
生来不讨喜 2021-01-12 18:29

I want to access local variable declared in C in inline arm Assembly. How do I do that?

Global variables can be accessed like this,

int temp = 0;
Fun         


        
相关标签:
2条回答
  • 2021-01-12 18:58

    According to GCC docs: 6.45.2.3 Output Operands

    You can pass the values like this:

    #include <stdio.h>
    
    int main(int argc, char *argv[]) {
    
      int src = 1;
      int dst;   
    
      asm ("mov %1, %0\n\t add $1, %0" : "=r" (dst) : "r" (src));
    
      printf("0x%X\n", dst);
    
      return 0;
    }
    

    After your asm code you put the ':' character and the values you want to pass like this: "(=|+)(r|m)" (variable). Use '=' when overriding the value and '+' when reading or overriding the value, then use the 'r' letter if the value resides in a register or 'm' if it resides in memory.

    0 讨论(0)
  • 2021-01-12 19:02

    r minimal runnable example

    main.c

    #include <assert.h>
    #include <inttypes.h>
    
    int main(void) {
        uint64_t in0 = 1, in1 = 2, out;
        __asm__ (
            "add %[out], %[in0], %[in1];"
            : [out] "=r" (out)
            : [in0] "r"  (in0),
              [in1] "r"  (in1)
        );
        assert(in0 == 1);
        assert(in1 == 2);
        assert(out == 3);
    }
    

    GitHub upstream.

    Compile and run:

    sudo apt-get install qemu-user gcc-aarch64-linux-gnu
    aarch64-linux-gnu-gcc -std=c99 -ggdb3 -march=armv8-a -pedantic -Wall -Wextra -o main.out main.c
    qemu-aarch64 -L /usr/aarch64-linux-gnu -E LD_BIND_NOW=1 main.out
    

    Disassembly:

    gdb-multiarch -nh -batch -ex 'disassemble/rs main' add.out
    

    Output excerpt:

    Dump of assembler code for function main:
    add.c:
    6   int main(void) {
       0x0000000000000764 <+0>: fd 7b bd a9 stp x29, x30, [sp, #-48]!
       0x0000000000000768 <+4>: fd 03 00 91 mov x29, sp
    
    7       uint64_t in0 = 1, in1 = 2, out;
       0x000000000000076c <+8>: 20 00 80 d2 mov x0, #0x1                    // #1
       0x0000000000000770 <+12>:    e0 0f 00 f9 str x0, [sp, #24]
       0x0000000000000774 <+16>:    40 00 80 d2 mov x0, #0x2                    // #2
       0x0000000000000778 <+20>:    e0 13 00 f9 str x0, [sp, #32]
    
    8       __asm__ (
       0x000000000000077c <+24>:    e0 0f 40 f9 ldr x0, [sp, #24]
       0x0000000000000780 <+28>:    e1 13 40 f9 ldr x1, [sp, #32]
       0x0000000000000784 <+32>:    00 00 01 8b add x0, x0, x1
       0x0000000000000788 <+36>:    e0 17 00 f9 str x0, [sp, #40]
    
    9           "add %[out], %[in0], %[in1];"
    10          : [out] "=r" (out)
    11          : [in0] "r"  (in0),
    12            [in1] "r"  (in1)
    13      );
    

    So we see that r translated into stack sp relative str loads, which is where local variables live.

    Tested in Ubuntu 18.10, GCC 8.2.0, QEMU 2.12.

    0 讨论(0)
提交回复
热议问题