考虑以下小功能:
void foo(int* iptr) {
iptr[10] = 1;
__asm__ volatile ("nop"::"r"(iptr):);
iptr[10] = 2;
}
Run Code Online (Sandbox Code Playgroud)
使用gcc,它将编译为:
foo:
nop
mov DWORD PTR [rdi+40], 2
ret
Run Code Online (Sandbox Code Playgroud)
请特别注意,即在第一次写iptr,iptr[10] = 1根本不会发生:内联汇编nop是在函数的第一件事,只有最后写2(会出现ASM呼叫后)。显然,编译器决定只需要提供其iptr 自身值的最新版本,而不需要提供其指向的内存。
我可以告诉编译器,内存必须是最新的memory,就像这样:
void foo(int* iptr) {
iptr[10] = 1;
__asm__ volatile ("nop"::"r"(iptr):"memory");
iptr[10] = 2;
}
Run Code Online (Sandbox Code Playgroud)
结果为预期的代码:
foo:
mov DWORD PTR [rdi+40], 1
nop
mov DWORD PTR [rdi+40], 2
ret
Run Code Online (Sandbox Code Playgroud)
但是,这太强了,因为它告诉编译器必须写入所有内存。例如,在以下功能中:
void foo2(int* iptr, long* …Run Code Online (Sandbox Code Playgroud)