Jayesh Saita
Jayesh Saita

Reputation: 327

Why is there no inbuilt swap function in C but there is xchg in Assembly?

Recently I came across Assembly language. x86 assembly has an xchg instruction which swaps the contents of two registers.

Since every C code is first converted to Assembly, it would have been nice if there was a swap function inbuilt in C like in the header stdio.h. Then whenever the compiler detects the swap function, it could add the xchg directive in the assembly file.

So why this swap function was not implemented in C?

Upvotes: 5

Views: 2627

Answers (5)

Peter Cordes
Peter Cordes

Reputation: 365267

Besides what the other correct answers say, another part of your premise is wrong.

Only a really dumb compiler would want to actually emit xchg every time the source swapped variables, whether there's an intrinsic or operator for it or not. Optimizing compilers don't just transliterate C into asm, they typically convert to an SSA internal representation of the program logic, and optimize that so they can implement it with as few instructions as possible (or really in the most efficient way possible; using multiple fast instructions can be better than a single slower one).

xchg is rarely faster than 3 mov instructions, and a good compiler can simply change its local-variable <-> CPU register mapping without emitting any asm instructions in many cases. (Or inside a loop, unrolling can often optimize away swapping.) Often you need only 1 or mov instructions in asm, not all 3. e.g. if only one of the C vars being swapped needs to stay in the same register, you can do:

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

See also Why is XCHG reg, reg a 3 micro-op instruction on modern Intel architectures?

Also note that xchg [mem], reg is atomic (implicit lock prefix), and thus is a full memory barrier, and much slower than 3 mov instructions, and with much higher impact on surrounding code because of the memory-barrier effect.


If you do actually need to exchange registers, 3x mov is pretty good. Often better than xchg reg,reg because of mov elimination, at the cost of more code-size and a tmp reg.

There's a reason compilers never use xchg. If xchg was a win, compilers would look for it as a peephole optimization the same way they look for inc eax over add eax,1, or xor eax,eax instead of mov eax,0. But they don't.

(semi-related: swapping 2 registers in 8086 assembly language(16 bits))

Upvotes: 3

user1159290
user1159290

Reputation: 1003

That would work for variables that fit in the register and are in the register. It would not work for large struct or variables held in memory (If you load a variable A in reg X and another, say B in reg Y, and swap them, you could skip the swapping and load A in Y and B in X directly).

Having said said, nothing prevent the compiler for a given architecture to use the swap instruction to compile:

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

... If those happens to be in registers: the fact that it is not in C does not mean the compiler does not use it.

Upvotes: 5

There are two points which can explain why swap() is not in C

1. Function call semantics:
Including a swap() function would break a very fundamental design decision in C: swap() can only work with pass-by-reference semantics (which C++ added to the language, but which are absent in C), not with pass-by-value.

2. Diversity of available assembler instructions
Apart from that, there is usually quite a number of assembler instructions on any given CPU architecture which are totally inaccessible from pure C. This includes instructions as diverse as interrupt handling instructions, virtual memory space manipulating instructions, I/O instructions, bit fiddling instructions (google the PPC instruction rlwimi for an especially powerful example of this), etc.

It is simply impossible to include any significant number of these in a general purpose language like C.

Some of these are crucial for implementing operating systems, which is why any OS must include at the very least some small amounts of assembler code. They are usually encapsulated in some functions with inline assembler or defined in the kernel headers as preprocessor directives. Other instructions are less important, or only good for optimizations, these may be generated by optimizing compilers, and many compilers do generate them (the whole class of vector functions fall in this category).

In the face of this vast diversity, the designers of C just had to cut it somewhere. And they opted for providing whatever is representable as simple operators like (+, -, ~, &, |, !, &&, ||, etc.), but did not provide anything that would require function call syntax like the swap() function you propose.

Upvotes: 5

edmz
edmz

Reputation: 8492

Even though xchg is a very elementary instruction, this doesn't mean C must have its equivalent. The fact that C sometimes maps directly to assembly is not very relevant; the standard says nothing about "assembly" (why map to assembly and not another low-level language?).

You might also ask: Why does C not have built-in vector instructions? They're becoming largely available!

There's also compiler's help: swapping variables is a very visible pattern, so such optimization shouldn't be hard to implement. And you also have inline asm, should you need it.

Upvotes: 1

Eugene Sh.
Eugene Sh.

Reputation: 18371

C is a cross-platform language. Assembly is architecture specific. Not every architecture has such an instruction. Moreover, C, as a high-level language doesn't have to correspond to the machine-level instruction set and features, as it's purpose is to bridge between the "human" language and the machine language, not to mimic it. Said that, a C compiler for this specific architecture might have an extension for this swapping instruction or optimize the swapping code to use this instruction if smart enough.

Upvotes: 9

Related Questions