为什么C中没有内置交换功能但是汇编中有xchg?

时间:2016-11-09 17:03:39

标签: c assembly

最近我遇到了汇编语言。 x86程序集有an xchg instruction,它交换了两个寄存器的内容。

由于每个C代码都首先转换为汇编代码,如果在C中构建了一个交换函数,就像在标题stdio.h中一样。然后,只要编译器检测到交换函数,它就可以在汇编文件中添加xchg指令。

那么为什么这个交换功能没有在C中实现?

5 个答案:

答案 0 :(得分:7)

C 是一种跨平台语言。装配是特定于架构的。并非每个架构都有这样的指令。此外, C ,作为一种高级语言并不一定要与机器级指令集和功能相对应,因为它的目的是在#34之间架起桥梁。 ;人"语言和机器语言,而不是模仿它。说,针对此特定体系结构的 C 编译器可能具有此交换指令的扩展,或者如果足够智能则优化交换代码以使用此指令。

答案 1 :(得分:5)

这适用于适合寄存器并位于寄存器中的变量。它不适用于内存中保存的大型结构或变量(如果在reg X中加载变量A,在reg Y中加上B,并交换它们,则可以跳过交换并直接在Y和B中加载A )。

话虽如此,没有什么能阻止编译器使用交换指令进行编译:

 int a;
 int b;
 int tmp;
 tmp=a;
 a=b;
 b=tmp;

...如果那些恰好在寄存器中:事实上它不在C中并不意味着编译器不使用它。

答案 2 :(得分:4)

有两点可以解释为什么swap()不在C

<强> 1。函数调用语义:
包含swap()函数会在C中打破一个非常基本的设计决策:swap()只能使用传递引用语义(C ++添加到语言中,但在C中不存在),而不是传递价值。

<强> 2。可用汇编指令的多样性
除此之外,在任何给定的CPU架构上通常都有相当多的汇编指令,它们完全无法从纯C中访问。这包括各种指令,如中断处理指令,虚拟存储空间操作指令,I / O指令,位功能指令(谷歌PPC指令rlwimi以获得一个特别有力的例子)等等。

根本不可能在C等通用语言中包含任何大量的这些。

其中一些对于实现操作系统至关重要,这就是为什么任何操作系统必须至少包含一些少量的汇编代码。它们通常使用内联汇编程序封装在某些函数中,或者在内核头文件中定义为预处理程序指令。其他指令不太重要,或者只对优化很有用,这些指令可以通过优化编译器生成,并且许多编译器确实生成它们(整个类的向量函数属于这一类)。

面对这种巨大的多样性,C的设计师不得不将它切割到某个地方。他们选择提供任何可表示的简单操作符,如(+, - ,〜,&amp;,|,!,&amp;&amp;,||等),但没有提供任何需要函数调用语法的东西。您建议的swap()功能。

答案 3 :(得分:1)

除了其他正确答案所说的以外,前提的另一部分是错误的。

只有真正笨的编译器才希望每次源交换变量时都发出xchg,无论是否有内部变量或运算符。优化的编译器不仅将C转换为asm,而且通常将其转换为程序逻辑的SSA内部表示形式,并进行优化以使它们可以使用尽可能少的指令来实现(或实际上以最有效的方式;使用多个快速的指令可能比单个慢的指令更好。)

xchg很少比3条mov指令快,而且一个好的编译器可以在许多情况下简单地更改其局部变量<-> CPU寄存器映射而无需发出任何asm指令。 (或者在循环内,展开通常可以优化交换。)在asm中,通常只需要1或mov条指令,而不是全部3条。如果仅一个被交换的C变量需要保留在同一寄存器中,则可以执行以下操作:

# start:   x in EAX,  y in ECX 
mov    edx, eax
mov    eax, ecx
# end:     y in EAX,  x in EDX

另请参阅Why is XCHG reg, reg a 3 micro-op instruction on modern Intel architectures?

还要注意,xchg [mem], reg是原子的(隐式lock前缀),因此是一个完整的内存屏障,并且比3条mov指令要慢得多,并且对周围环境的影响要大得多。代码,因为有内存屏障效应。


如果您实际上需要交换寄存器,则3倍mov很好。由于省去了xchg reg,reg,因此通常比mov更好,但代价是更多的代码大小和tmp reg。

编译器从不使用xchg是有原因的。如果xchg获胜,则编译器会将其视为窥视孔优化,就像他们在inc eax上寻找add eax,1xor eax,eax而不是mov eax,0一样。但是他们没有。

(半相关:swapping 2 registers in 8086 assembly language(16 bits)

答案 4 :(得分:0)

即使xchg是一个非常基本的指令,但这并不意味着C必须具有等效性。 C 有时直接映射到汇编的事实并不是很相关;该标准没有提及&#34;组装&#34; (为什么要映射到汇编而不是另一种低级语言?)。

您可能还会问:为什么C没有内置向量指令?它们已大量上市!

还有编译器的帮助:交换变量是一种非常明显的模式,因此这种优化不应该难以实现。如果需要,您还可以内联asm