Assembly Flow Control: Loops

CS 301 Lecture, Dr. Lawlor, 2005/09/19

In the last lecture, I lapsed into a peculiar variant of C, where "if" statements just control "goto" statements.  I should point out that this is perfectly legal C--
#include <stdio.h>

int main() {
int i=0;
if (i>=10) goto byebye;
printf("Not too big: i==%d\n",i);
byebye: printf("All done!\n");
}
This way of writing C is quite similar to assembly--in fact, there's probably one-to-one correspondence between lines of C code written this way and machine language instructions.  More complicated C, like the "for" construct, expands out to many lines of assembly.

Here's an expanded version of a C "for (i=0;i<10;i++) printf..." program:
#include <stdio.h>

int main() {
int i=0;
start: if (i>=10) goto end;
printf("In loop: i==%d\n",i);
i++;
goto start;
end: printf("All done!\n");
}
You've got to convince yourself that this is really equivalent to the "for" loop in all cases.

All C flow-control constructs can be written using just "if" and "goto", which usually map one-to-one to something in assembly.

Normal C
Expanded C
if (A) {...}
if (!A) goto END;
...
END:
if (!A) {...}
if (A) goto END;
...
END:
if (A&&B) {...}
if (!A) goto END;
if (!B) goto END;
...
END:
if (A||B) {...}
if (A) goto STUFF;
if (B) goto STUFF;
goto END;
STUFF: ...
END:
while (A) {...}
START: if (!A) goto END;
...
goto START;
END:
do {...} while (A)
START: ...
if (A) goto START;
for (i=0;i<n;i++) {...}
i=0;          /* Version A */
START: if (i>=n) goto END;
...
i++;
goto START;
END:
for (i=0;i<n;i++) {...}

i=0;         /* Version B */
goto COMPARE;
START:
...
i++;
COMPARE: if (i<n) goto START;
END:

Note that the last two translations of the "for" concept (labelled Version A and Version B) both compute the same thing.  Which one is faster? They're probably pretty close to the same!