The obvious answer is that XOR is faster. To do a subtract, you have to propagate the carry bit from the least-significant bit to the most-significant bit. In XOR you don't have to do that because the output of every bit is independent of the other adjacent bits. Probably, there are ALU pipeline designs where you don't pay an explicit penalty. But not all, and so XOR is faster. Surely, someone as awesome as Raymond C…
The non-obvious bit is why there isn't an even faster and shorter "mov ,0" instructions - the processors started short-circuiting xor , much later.
XOR'ing a register with itself is the idiom for zeroing it out. Why not sub?
91–100 of 231 posts
Re: XOR'ing a register with itself is the idiom for zeroing it out. Why not sub?
#92Earlier quoted context omitted.
Quite a few architectures have a dedicated 0 register.
Yep. The XOR trick - relying on special use of opcode rather than special register - is probably related to limited number of (general purpose) registers in typical '70 era CPU design (8080, 6502, Z80, 8086).
Re: XOR'ing a register with itself is the idiom for zeroing it out. Why not sub?
#93Earlier quoted context omitted.
His point is that in x86 there is no performance difference but everyone except his colleague/friend uses xor, while sub actually leaves cleaner flags behind. So he suspects its some kind of social convention selected at random and then propagated via spurious arguments in support (or that it “looks cooler” as a bit of a term of art). It could also be as a result of most people working in assembly being aware of the…
I think an even more likely explanation would be that x86 assembly programmers often were, or learned from other-architecture assembly programmers. Maybe there's a place where it makes more sense and it can be so attributed. 6502 and 68k being first places I would look at.
8080/Z80 is probably where XOR A got a lead over SUB A, but they are also the same number of cycles.
Re: XOR'ing a register with itself is the idiom for zeroing it out. Why not sub?
#94Earlier quoted context omitted.
That comment is not very useful without pointing to realworld CPUs where SUB is more expensive than XOR ;) E.g. on Z80 and 6502 both have the same cycle count.
The 6502 doesn't support XOR A or SUB A, and in fact doesn't have a SUB opcode at all, only SBC (subtract with carry, requiring an extra opcode to set the carry flag beforehand).
EOR and SBC still have the same cycle counts though.
Re: XOR'ing a register with itself is the idiom for zeroing it out. Why not sub?
#95Earlier quoted context omitted.
That comment is not very useful without pointing to realworld CPUs where SUB is more expensive than XOR ;) E.g. on Z80 and 6502 both have the same cycle count.
Harvard Mark I? Not sure why people think programming started with Z80.
Re: XOR'ing a register with itself is the idiom for zeroing it out. Why not sub?
#96Earlier quoted context omitted.
The non-obvious bit is why there isn't an even faster and shorter "mov ,0" instructions - the processors started short-circuiting xor , much later.
Right, like a “set reg to zero” instruction. One byte. Just encodes the operation and the reg to zero. I’m surprised we didn’t have it on those old processors. Maybe the thinking was that it was already there: xor reg,reg.
One-byte INC/DEC was dropped with x86-64, and PUSH/POP are almost obsolete in APX due to its addition of PUSH2/POP2, leaving only the least useful of the five in the most recent incantation of the instruction set.
Re: XOR'ing a register with itself is the idiom for zeroing it out. Why not sub?
#97The obvious answer is that XOR is faster. To do a subtract, you have to propagate the carry bit from the least-significant bit to the most-significant bit. In XOR you don't have to do that because the output of every bit is independent of the other adjacent bits. Probably, there are ALU pipeline designs where you don't pay an explicit penalty. But not all, and so XOR is faster. Surely, someone as awesome as Raymond C…
XOR and SUB have had identical cycle counts and latencies since the 8088. That's because you can "look ahead" when doing carries in binary. It's just a matter of how much floorspace on the chip you want to use. https://en.wikipedia.org/wiki/Carry-lookahead_adder The only minor difference between the two on x86, really, is SUB sets OF and CF according to the result while XOR always clears them.
Re: XOR'ing a register with itself is the idiom for zeroing it out. Why not sub?
#98Earlier quoted context omitted.
The non-obvious bit is why there isn't an even faster and shorter "mov ,0" instructions - the processors started short-circuiting xor , much later.
Right, like a “set reg to zero” instruction. One byte. Just encodes the operation and the reg to zero. I’m surprised we didn’t have it on those old processors. Maybe the thinking was that it was already there: xor reg,reg.
Re: XOR'ing a register with itself is the idiom for zeroing it out. Why not sub?
#99Earlier quoted context omitted.
Yep. The XOR trick - relying on special use of opcode rather than special register - is probably related to limited number of (general purpose) registers in typical '70 era CPU design (8080, 6502, Z80, 8086).
Unfortunately, 6502 can't XOR the accumulator with itself. I don't recall if the Z80 can, and loading an immediate 0 would be most efficient on those anyway.
Re: XOR'ing a register with itself is the idiom for zeroing it out. Why not sub?
#100Earlier quoted context omitted.
Quite a few architectures have a dedicated 0 register.
Yep. The XOR trick - relying on special use of opcode rather than special register - is probably related to limited number of (general purpose) registers in typical '70 era CPU design (8080, 6502, Z80, 8086).