考虑下面这段代码。
#include <stdio.h>
void f(int *x, int *y)
{
(*x)++;
(*y)++;
}
int main()
{
int x=5, y=5;
f(&x, &y);
return 0;
}
我知道函数f不是可重入的。我想的一件愚蠢的事情是在一行中做(* x)++ +(* y)++并丢弃总和。我想知道会生成多个汇编指令来评估这个表达式。中断是否会在表达式的评估之间提供?
答案 0 :(得分:1)
你不会得到任何原子......
c.o: file format elf64-x86-64
Disassembly of section .text:
0000000000000000 <f>:
0: 55 push %rbp
1: 48 89 e5 mov %rsp,%rbp
4: 48 89 7d f8 mov %rdi,-0x8(%rbp)
8: 48 89 75 f0 mov %rsi,-0x10(%rbp)
c: 48 8b 45 f8 mov -0x8(%rbp),%rax
10: 8b 00 mov (%rax),%eax
12: 8d 50 01 lea 0x1(%rax),%edx
15: 48 8b 45 f8 mov -0x8(%rbp),%rax
19: 89 10 mov %edx,(%rax)
1b: 48 8b 45 f0 mov -0x10(%rbp),%rax
1f: 8b 00 mov (%rax),%eax
21: 8d 50 01 lea 0x1(%rax),%edx
24: 48 8b 45 f0 mov -0x10(%rbp),%rax
28: 89 10 mov %edx,(%rax)
2a: 5d pop %rbp
2b: c3 retq
使用-O2
可以获得更好的效果,但它仍然不是原子的。
c.o: file format elf64-x86-64
Disassembly of section .text:
0000000000000000 <f>:
0: 83 07 01 addl $0x1,(%rdi)
3: 83 06 01 addl $0x1,(%rsi)
6: c3 retq
并且,至少对于GCC,为(*x)++ + (*y++)
生成完全相同的代码。无论如何,你可以对你的问题进行一些阐述吗?只要x
和y
在不同的条目上不相同,您就太宽泛了,并且此代码 可重入。否则,您应该向我们提供有关您的意图的更多详细信息。
编辑:它(显然,除非有一些隐藏的黑魔法......)不可能在x86(-64)架构上原子地做这样的事情。无论如何,如果在单个指令中完成操作,则考虑操作“原子”是不可移植的。这是特定于x86(-64)CPU。