是否可以中断表达式的评估

时间:2015-08-30 05:12:01

标签: c interrupt reentrancy

考虑下面这段代码。

#‎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)++并丢弃总和。我想知道会生成多个汇编指令来评估这个表达式。中断是否会在表达式的评估之间提供?

1 个答案:

答案 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++)生成完全相同的代码。无论如何,你可以对你的问题进行一些阐述吗?只要xy在不同的条目上不相同,您就太宽泛了,并且此代码 可重入。否则,您应该向我们提供有关您的意图的更多详细信息。

编辑:它(显然,除非有一些隐藏的黑魔法......)不可能在x86(-64)架构上原子地做这样的事情。无论如何,如果在单个指令中完成操作,则考虑操作“原子”是不可移植的。这是特定于x86(-64)CPU。