我想访问内联arm Assembly中C语言声明的局部变量。我怎么做?
可以像这样访问全局变量,
int temp = 0;
Function(){
__asm(
".global temp\n\t"
"LDR R2, =temp\n\t"
"LDR R2, [R2, #0]\n\t"
);
}
但是如何访问局部变量?我尝试将“.global”更改为“.local”以获取局部变量,但它生成了错误(未定义引用`temp')。我使用的IDE是KEIL。
有什么想法吗?提前致谢。
根据GCC文件:6.45.2.3 Output Operands
您可以传递这样的值:
#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;
}
在您的asm代码之后,您将':'
字符和您想要传递的值放在这样:"(=|+)(r|m)" (variable)
。在覆盖值时使用'='
,在读取或覆盖值时使用'+'
,如果值驻留在寄存器中,则使用'r'
字母;如果值驻留在内存中,则使用'm'
。
r
最小的可运行的例子
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);
}
编译并运行:
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
拆卸:
gdb-multiarch -nh -batch -ex 'disassemble/rs main' add.out
输出摘录:
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 );
所以我们看到r
翻译成堆栈sp
相对str
加载,这是局部变量存在的地方。
在Ubuntu 18.10,GCC 8.2.0,QEMU 2.12中测试。