XOR compares the two operands bit by bit and stores the result in the first. A result bit is 1 when the two bits differ and 0 when they are the same. With a mask, every 1 in the mask flips the matching bit and every 0 leaves it alone.
| dst bit | src bit | result |
|---|---|---|
| 0 | 0 | 0 |
| 0 | 1 | 1 |
| 1 | 0 | 1 |
| 1 | 1 | 0 |
Forms and flags
Same operand rules as AND and OR: register or memory destination, register, memory or immediate source, equal sizes, no memory-to-memory, no segment registers. CF and OF are cleared, SF ZF PF describe the result, AF is undefined.
Idioms
XOR AX, AX is the usual way to zero a register. Every bit is the same as itself, so the result is 0; it is two bytes long where MOV AX, 0 takes three, and it also leaves ZF=1 and CF=0. The difference matters when you need the flags kept: MOV does not touch them, XOR does.
XOR undoes itself: applying the same mask twice gives back the original value. That is the idea behind toggling a bit each time a key is pressed, simple XOR "encryption", and drawing a cursor that disappears when drawn again. XOR AX, BX is zero exactly when AX equals BX, though CMP is the normal way to compare. XOR AL, 0FFh flips all bits like NOT, but unlike NOT it sets the flags.
You may meet the trick of swapping two registers with three XORs; on the 8086 XCHG does it in one instruction and is easier to read.
MOV AL, 5Ah ; 0101 1010CALL SHOWBINXOR AL, 0Fh ; flip the low nibbleCALL SHOWBIN ; 0101 0101XOR AL, 0Fh ; again: back to 5AhCALL SHOWBINXOR AL, AL ; zero, ZF = 1CALL SHOWBINSHOWBIN PROC NEAR ; print AL as 8 binary digits and a spacePUSHF ; keep the caller's flagsPUSH AXPUSH BXPUSH CXPUSH DXMOV BL, ALMOV CX, 8NEXTBIT:SHL BL, 1 ; the top bit falls into CFMOV DL, "0"ADC DL, 0 ; "0" + CF = "0" or "1"MOV AH, 02hINT 21hLOOP NEXTBITMOV DL, " "MOV AH, 02hINT 21hPOP DXPOP CXPOP BXPOP AXPOPFRETSHOWBIN ENDP