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
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.
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.