Low Level Control Structures

Chapter 7

Statement Labels

  • labels stand in as symbolic names for addresses.

  • You can do three things with (code) labels: transfer control to a label via a (conditional or unconditional) jump instruction, call a label via the call instruction, and take the address of a label. Taking the address of a label is useful when you want to indirectly transfer control to that address at a later point in your program.

stmtLbl:
 .
 .
 .
        mov rcx, offset stmtLbl2
 .
 .
 .
        lea rax, stmtLbl
 .
 .
 .
stmtLbl2:

Using Local Symbols in Procedures

  • Statement labels you define within a proc/endp procedure are local to that procedure

  • If you really want to access a statement (or any other) label outside a procedure, you can use the option directive to turn off local scope within a section of your program

Initializing Arrays with Label Addresses

  • MASM also allows you to initialize quad-word variables with the addresses of statement labels.

Trampolines

  • In the rare case you need to branch to a location beyond the range of the 6-byte jcc instructions you can use a trampoline such as the on below :

  • The opposite conditional branch transfers control to the normal fall though point in the code. If the condition is true, control transfers to a memory indirect jump that jumps to the original target location via a 64-bit pointer.

Conditional Move Instructions

  • Because branches can be somewhat expensive to execute, the x86-64 CPUs support a set of conditional move instructions, cmovcc.

cmovcc Instructions That Test Flags
cmovcc Instructions That Test Flags
cmovcc Instructions for Unsigned Comparisons
cmovcc Instructions for Signed Comparisons
  • In addition, a set of conditional floating-point move instructions (fcmovcc) will move data between ST0 and one of the other FPU registers on the FPU stack. Sadly, these instructions aren’t all that useful in modern programs.

Implementing Common Control Structures in MASM

Complex if Statements Using Complete Boolean Evaluation

Short-Circuit Boolean Evaluation

Switch Statement

if/else Implementation of switch

Indirect Jump switch Implementation

Noncontiguous Jump Table Entries and Range Limiting

Sparse Jump Tables

  • The current implementation of the switch statement has a problem. If the case values contain nonconsecutive entries that are widely spaced, the jump table could become exceedingly large.

State Machines and Indirect Jumps

  • Another control structure commonly found in assembly language programs is the state machine. A state machine uses a state variable to control program flow.

  • So what is a state machine? In basic terms, it is a piece of code that keeps track of its execution history by entering and leaving certain states.

  • Suppose you have a procedure and want to perform one operation the first time you call it, a different operation the second time you call it, yet something else the third time you call it, and then something new again on the fourth call. After the fourth call, it repeats these four operations in order.

  • Technically, this procedure is not the state machine. Instead, the variable state and the cmp/jne instructions constitute the state machine. The procedure is little more than a switch statement implemented via the if/then/elseif construct.

  • It’s common to use an indirect jump to implement a state machine in assembly language. Rather than having a state variable that contains a value like 0, 1, 2, or 3, we could load the state variable with the address of the code to execute upon entry into the procedure.

Loops

While loops

Do-While loops

forever/endfor Loops

for Loops

The break and continue Statements

  • To convert a break statement to pure assembly language, just emit a goto/jmp instruction that transfers control to the first statement following the end of the loop to exit. You can do this by placing a label after the loop body and jumping to that label.

  • In pure assembly language, convert the appropriate control structures to assembly and replace the goto with a jmp instruction.

Registers in loops

  • Registers are more efficient than memory locations and are perfect for manipulating data. But due to their limited availability, they must used alongside the stack. Whenever a register is to be accessed, it's value must be preserved and should be restored after we are done with it.

  • Register corruption is one of the primary sources of bugs in loops in assembly language programs, so always keep an eye out for this problem.

Loop Performance Improvements

  1. Moving the Termination Condition to the End of a Loop.

  2. Executing the Loop Backward

  3. Using Loop-Invariant Computations - A loop-invariant computation is a calculation that appears within a loop that always yields the same result. You needn’t do such computations inside the loop. You can compute them outside the loop and reference the value of the computations inside the loop.

  4. Using Induction Variables - you can reduce the execution time of the body of the loop by using induction variables. An induction variable is one whose value depends entirely on the value of another variable.

Last updated