XOR has 3 basic uses: To invert bits based in a mask; To get the result of different bits in both operands or as a caryless add.
This kind of code is a trick to swap values without using a temporary variable, but it isn't a good one. Take a look at this two optimized (by the compiler, using -O2 option) functions f() and g():
Code:
; void f( int *a, int *b )
; { int t; t = *a; *a = *b; *b = t; }
f:
mov eax,[rdi]
mov edx,[rsi]
mov [rdi],edx
mov [rsi],eax
ret
; void g( int *a, int *b )
; { *a ^= *b; *b ^= *a; *a ^= *b; }
g:
mov eax,[rdi]
xor eax,[rsi]
mov [rdi],eax
xor eax,[rsi]
mov [rsi],eax
xor [rdi],eax
ret