'How do I access local C variable in arm inline assembly?
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;
Function(){
__asm(
".global temp\n\t"
"LDR R2, =temp\n\t"
"LDR R2, [R2, #0]\n\t"
);
}
But how do I access local variables? I tried changing ".global" to ".local" for local variables, but it generated error (undefined reference to `temp'). The IDE I am using is KEIL.
Any thoughts? Thanks in Advance.
Solution 1:[1]
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.
Solution 2:[2]
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);
}
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.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | Alexis Wilke |
| Solution 2 | Ciro Santilli |
