How is switch fall-through (one case flowing into the next without a break) implemented in assembly?
The compiler lets the falling-through case end without a jump, so control simply runs on into the next case's code at a shared "merge" label.
* Fall-through is the absence of a jump into a shared merge block. *
Fall-through is the absence of a break, so in assembly it's the absence of a jump — execution just keeps going. The trick is arranging the code so the next case's body sits right after, with a label both paths can reach.
C code:
case 2:
w = y/z;
// fall through (no break)
case 3:
w += z;
break;
Assembly layout:
.L9: # case 3 entered directly from the jump table
movl $1, %eax # w = 1 (w wasn't initialized on this path)
jmp .L6 # skip case 2's body, go to the shared code
.L5: # case 2 entered from the jump table
movq %rsi, %rax
cqto
idivq %rcx # w = y / z
# no jump here -- fall straight through into .L6
.L6: # shared "merge" point
addq %rcx, %rax # w += z
ret
Case 3 (.L9) jumps over case 2's division to reach .L6; case 2 (.L5) computes y/z and then falls through into the very same .L6. The merge label .L6 runs w += z for both. That's fall-through expressed as deliberate code placement rather than any special instruction.
Go deeper:
Switch statement (Wikipedia) — fall-through semantics across languages.