Flow Control in Assembly

CS 301 Lecture, Dr. Lawlor

In the last lecture, I described a peculiar variant of C, where "if" statements only contain "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 a 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("In loop: i==%d\n",i); }" program:
#include <stdio.h>

int main() {
int i=0;
goto test;
start: {
printf("In loop: i==%d\n",i);
}
i++;
test: if (i<10) goto start;
printf("All done!\n");
}
Try this out in NetRun!

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.  For example, in funk_emu, the if/goto combination can be implemented with a compare and jump-if-less instruction sequence--the exact same sequence found in most real assembly languages!

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)  {
  ...
}
goto TEST;
START:
{
  ...
}
TEST: if (A) goto START;
do {
  ...
} while (A)
START:
{
  ...
}
if (A) goto START;
for (i=0;i<n;i++)
{
  ...
}
i=0;         /* Version B */
goto TEST;
START:
{
  ...
}
i++;
TEST: if (i<n) goto START;
for (i=0;i<n;i++)
{
  ...
}

i=0;          /* Version A */
START: if (i>=n) goto END;
{
  ...
}
i++;
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? I claim version (A) is faster, since there's only one (conditional) goto per loop, instead of two gotos in version (B)--one conditional and one unconditional.