sb
sb
rs2, off(rs1)
mem[rs1 + off] = rs2
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

sb stores a single byte (8 bits) to memory — the smallest store there is. It is the writing counterpart to the lb/lbu loads. The form is sb rs2, offset(rs1): take the value in source register rs2 and write its lowest 8 bits to the address in base register rs1 plus the offset (the store layout from sw, source register first).

Of the 32 bits in the register, only the lowest 8 are written; the rest are dropped. As with all stores there is no signed/unsigned variant, because narrowing has no missing bits to fill — it simply keeps the low byte. If the value was larger than a byte, the overflow is silently discarded: storing 300 actually writes 44, since 300 wraps around past 256.

A byte is the finest unit memory offers, so sb is the tool for building data one byte at a time: assembling text character by character, filling a buffer, writing individual color values. Bytes sit one address apart, so a loop advances by adding 1.

The classic exercise is writing text by hand: store each character's code with sb, finish with a 0 byte to mark the end, then print it. Watching the codes 72, 105, 0 in memory turn into the printed word Hi makes concrete what a string really is underneath — just bytes in consecutive memory slots, ended by a zero. Only the one targeted byte changes on each store; its neighbours are untouched.