最近我遇到了汇编语言。 x86程序集有an xchg instruction,它交换了两个寄存器的内容。
由于每个C代码都首先转换为汇编代码,如果在C中构建了一个交换函数,就像在标题stdio.h
中一样。然后,只要编译器检测到交换函数,它就可以在汇编文件中添加xchg指令。
那么为什么这个交换功能没有在C中实现?
答案 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,1
或xor eax,eax
而不是mov eax,0
一样。但是他们没有。
(半相关:swapping 2 registers in 8086 assembly language(16 bits))
答案 4 :(得分:0)
即使xchg
是一个非常基本的指令,但这并不意味着C必须具有等效性。 C 有时直接映射到汇编的事实并不是很相关;该标准没有提及&#34;组装&#34; (为什么要映射到汇编而不是另一种低级语言?)。
您可能还会问:为什么C没有内置向量指令?它们已大量上市!
还有编译器的帮助:交换变量是一种非常明显的模式,因此这种优化不应该难以实现。如果需要,您还可以内联asm
。