bne
bne
rs1, rs2, label
if (rs1 != rs2) goto label
R
31–25funct7
24–20rs2
19–15rs1
14–12funct3
11–7rd
6–0opcode
I
31–20imm[11:0]
19–15rs1
14–12funct3
11–7rd
6–0opcode
S
31–25imm[11:5]
24–20rs2
19–15rs1
14–12funct3
11–7imm[4:0]
6–0opcode
B
31–25imm[12,10:5]
24–20rs2
19–15rs1
14–12funct3
11–7imm[4:1,11]
6–0opcode
U
31–12imm[31:12]
11–7rd
6–0opcode
J
31–12imm[20,10:1,11,19:12]
11–7rd
6–0opcode

bne is the exact opposite of beq: branch if not equal. It compares two registers and jumps to the labelled position when they *differ*, continuing to the next instruction when they match. The form is bne rs1, rs2, label. (If branches, labels, and the idea of jumping based on a condition are new, the beq page lays them out.)

Between them, beq and bne handle every equal / not-equal decision. Which one you write is a question of how you shape the code, and assembly often phrases things in the inverted way from how you would think them. To run a block of code only when two values are equal, the neat trick is to branch *around* that block with bne — skip it when they differ, fall into it when they match.

The other big use is loops that should keep going as long as something stays true. A loop that runs while a value is not yet some target ends with a bne jumping back to the top. Walking through text fits this exactly: keep looping while the current character is not the zero byte that marks the end.

There is also a shorthand, bnez, for the very common case of comparing against zero — keep going while this value is not zero. Like beq, the comparison is plain equality of bits, with no signed-versus-unsigned subtlety to worry about.