How is a while loop translated to assembly, and how does it differ from a do-while?
A while becomes a do-while guarded by one initial test that can skip the loop entirely when the condition starts out false.
* while = do-while plus a leading guard so the body can run zero times. *
The difference between the two loops is purely when the condition is first checked: a do-while always runs the body at least once; a while might run it zero times. Compilers handle this by reusing the do-while shape and bolting on a pre-check:
while (Test) { Body }
becomes
if (!Test) goto done; // guard: skip the loop if false up front
do { Body } while (Test);
done:
Assembly:
cmpq ...
je .L_done # initial guard: skip body if test fails now
.L_loop:
# Body
cmpq ...
jne .L_loop # loop back while test still holds
.L_done:
Key difference from do-while: that leading guard. It guarantees the body executes zero times when the condition is false on entry — the defining behavior of while.
Optimization: If the compiler can prove the test is true on the first iteration (e.g. for (i=0; i<N; i++) with N a known positive constant), it deletes the guard entirely.
Go deeper:
Control flow (Wikipedia) — loop control flow and the pre-test shape.
Compiler Explorer (godbolt) — see the guard test appear or vanish across -O levels.