Assembly Terminology & Flow Control

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

Assembly Terminology

A "Register" is just an on-chip place to store data.  It's not memory.  They're stored right on the chip, they're incredibly fast (access is 0 clocks--even faster than cached memory) and they're only accessible via assembly.  There are many sorts of registers:
An "Instruction" is a binary code that tells the CPU to do something.  On modern machines, instructions are always an integral number of bytes long.  On "RISC" machines like UEMU, PowerPC, MIPS, or Itanium, instructions are fixed-size: often 32 or 64 bits.  On older "CISC" machines, like x86 or m68k, instructions can be as short as one byte, or dozens of bytes long.  Instruction encoding terminology includes:

Flow Control--Simple Conditionals

So you're running along: loading up registers with immediate and user values, doing arithmetic, and printing stuff out.  That's all easy enough.  But what happens when you want to write an "if" statement?
if (a<b) {
c=a+b;
}
In UEMU, the *only* conditional is the 0xC opcode--if register[j]>=register[k], increment register[i].  We can turn this into a conditional "skip next instruction" by using the program counter (register F) as the destination.  For example, the instruction 0xCFAB increments the program counter, and skips the next instruction, *if* register A>=register B.  If the body of the "if" statement is just one instruction, we *want* to skip that instruction if the condition doesn't hold!

So overall, we can translate the above "if" into
	0xCFAB  /* if (a>=b), skip the next instruction */
0xACAB /* c=a+b; */
which, if a<b, fails the test and just proceeds to the addition normally.  If (!a<b), which is the same as (a>=b), then the increment actually fires, and the addition is skipped.  The best way to check if you've coded a conditional properly (or any piece of code) is to imagine executing the thing, step by step.

Complicated Conditionals

The above trick works fine if the body of the conditional is only one instruction, but what if it's longer?  The standard (bizarre) solution is to set up a weird nest of JUMP (or goto) statements, like this (in C) translation of "if (A) ... else ...".  It's pretty easy if you can flip the test around as above:
	if (!A) goto END; /* skip "then" block if comparison failse */
... long bunch of stuff when the if succeeds ...
END: ... rest of program
This trick also makes it easy to do short-circuit boolean operations, like "if (A&&B)", where we want to immediately give up if A or B is false.
	if (!A) goto END; /* A failed */
if (!B) goto END; /* B failed */
... long bunch of stuff when the if succeeds ...
END: ... rest of program
If you really need the test to go the right way around, you can do the "skip THEN" trick:
	if (A) goto THEN; /* executes "then" block if comparison succeeds */
/* otherwise */ goto END; /* skips the "then" if the comparison fails */
THEN: ... long bunch of stuff when the if succeeds ...
END: ... rest of program
The basic idea is to use goto statements (since they're only one instruction long) to splice the "THEN" part of the if out of the rest of the program.  In most assembly languages, a comparison does a jump if it succeeds, so the UEMU conditional skip-followed-by-jump are a single instruction. 

The "skip THEN" trick also works for short-circuit boolean OR, like "if (A||B)":
	if (A) goto THEN; /* executes "then" block if A true */
if (B) goto THEN; /* executes "then" block if B true */
/* otherwise */ goto END; /* skips the "then" if the comparisons fail */
THEN: ... long bunch of stuff when the if succeeds ...
END: ... rest of program
The goto trick makes it easy to add an "ELSE" block too:
	if (...) goto THEN;
/* otherwise */ goto ELSE;
THEN: ... long bunch of stuff when the if succeeds ...
goto END;
ELSE: ... long bunch of stuff when the if fails ...
goto END;
END: ... rest of program