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);
}
GitHub 上游。
编译并运行:
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 中进行了测试。
.local
只是意味着具有静态链接的“全局”变量。如果您声明void foo(void) { static int bar; }
,则可以通过这种方式访问bar。然而,对于C程序员来说,这不是“本地”的正常概念,而是“静态”的概念。 - artless noise