Why MIPS uses R0 as "zero" when you could just XOR two registers to produce 0?
The zero-register on RISC CPUs is useful for two reasons:

It's a useful constant

Depending on restrictions of the ISA, you can't use a literal in some instructions encoding, but you can be sure you can use that r0 to get 0.

It can be used to synthesize other instructions

This is perhaps the most important point. As a ISA designer, you can trade-off a general purpose register to a zero-register to be able to synthesize other useful instructions. Synthesizing instructions is good because by having less actual instructions, you need less bits to encode an operation in a opcode, which frees-up space in the instruction encoding space. You can use that space to have e.g. bigger address offsets and/or literals.

The semantics of the zero-register is like /dev/zero on *nix systems: everything written to it is discarded, and you always read back 0.

Let's see a few examples of how we can make pseudo-instructions with the help of the r0 zero-register:

; ### Hypothetical CPU ###

; Assembler with syntax:
; op rd, rm, rn 
; =&gt; rd: destination, rm: 1st operand, rn: 2nd operand
; literal as #lit

; On an CPU architecture with a status register (which contains arithmetic status
; flags), `sub` can be used, with r0 as destination to discard result.
cmp rn, rm     ; =&gt; sub r0, rn, rm

; `add` instruction can be used as a `mov` instruction:
mov rd, rm     ; =&gt; add rd, rm, r0
mov rd, #lit   ; =&gt; add rd, r0, #lit

; Negate:
neg rd, rm     ; =&gt; sub rd, r0, rm

; On CPU without status flags,
nop            ; =&gt; add r0, r0, r0

; RISC-V's `jal` instruction -- Jump and Link: Jump to PC-relative instruction,
; save return address into rd; we can synthesize a `jmp` instruction out of it.
jmp dest       ; =&gt; jal r0, dest

; You can even load from an absolute (direct) address, for a usually small range
; of addresses by using a literal offset as an address.
ld rd, addr    ; =&gt; ld rd, [r0, #addr]


The case of MIPS

I looked more closely at the MIPS instruction set. There are a handful of pseudo-instructions that uses $zero; they are mainly used for branches. Here are some examples of what I've found:

move $rt, $rs          =&gt; add $rt, $rs, $zero

not $rt, $rs           =&gt; nor $rt, $rs, $zero

b Label                =&gt; beq $zero, $zero, Label ; a small relative branch

bgt $rs, $rt, Label    =&gt; slt $at, $rt, $rs
                          bne $at, $zero, Label

blt $rs, $rt, Label    =&gt; slt $at, $rs, $rt
                          bne $at, $zero, Label

bge $rs, $rt, Label    =&gt; slt $at, $rs, $rt
                          beq $at, $zero, Label

ble $rs, $rt, Label    =&gt; slt $at, $rt, $rs
                          beq $at, $zero, Label


As for why you have found only one instance of the $zero register in your disassembly, perhaps it's your disassembler that is smart enough to transform known sequences of instructions into their equivalent pseudo-instruction.

Is the zero-register really useful?

Well, apparently, ARM finds having a zero-register useful enough that in their (somewhat) new ARMv8-A core, which implement AArch64, there's now a zero-register in 64-bit mode; there wasn't a zero-register before. (The register is a bit special though, in some encoding contexts it's a zero-register, in others it instead designates the stack pointer)