Codementor Events

An Example in Assembly Language Control Flow

Published Oct 14, 2019Last updated Apr 10, 2020

This article is another in my series on understanding assembly language — it is a follow on to Conditional Logic in Assembly Language

Both these articles are written in plain C — not assembly language — but not structured C, rather C using if-goto, the style of control flow used in assembly language and machine code.

We're going to transform this simple bubble sort in C to remove the structure statements:

void bubbleSort ( int arr [], int n )
{
    for ( int i = 0; i < n-1; i++ ) {
        for ( int j = 0; j < n-i-1; j++ ) {
            if ( arr [j] > arr [j+1] ) {
                temp = arr [j];
                arr [i] = temp;
                arr [j] = temp;
            }
        }
    }
}

First, let's review the for-loop.  There are four sections to the for-loop:

for ( initialization; condition; increment )
    { body }

Control flow does initialization first, one time only, outside of the loop.  Next, the condition is tested to see if the loop is done.  Then, the body executes one time (an iteration).  And finally, the increment, followed by the condition retested to see if another iteration should happen.

Before we begin a first step is to transform the structured for-loops into slightly simpler yet still structured while-loops.

NB: One consideration here is whether the structured loop has any continue; statements because continue; in the for loop should run the increment followed by condition, etc..  Whereas, since a while loop doesn't have an increment part, a continue; therein goes right to the condition.

Since this code does not have continue; statements in the for-loops, the transformation is simple.  (Otherwise we would need to place a label at the increment part and replace continue; statements with a goto to that new label.)

void bubbleSort(int arr[], int n)
{ 
    int i = 0; // outer for-loop initialization
    while ( i < n-1 ) {
        int j = 0; // inner for-loop initialization
        while ( j < n-i-1 ) {
            if ( arr [j] > arr [j+1] ) {
                temp = arr [j];
                arr [i] = temp;
                arr [j] = temp;
            }
            j++; // inner for-loop increment
        }
        i++; // outer for-loop increment
    }
}

Next, let's do the if-goto for the outer while loop:

void bubbleSort(int arr[], int n)
{ 
    int i = 0; // outer for-loop initialization
outerLoopTop:
    if ( i >= n-1 ) goto outerLoopDone;  // exists the outer loop NB: condition reversed!
    int j = 0; 
    while ( j < n-i-1 ) {
        if ( arr [j] > arr [j+1] ) {
            temp = arr [j];
            arr [i] = temp;
            arr [j] = temp;
        }
        j++;
    }
    i++; // outer for-loop increment
    goto outerLoopTop;
outerLoopDone: ;
}

As explained in the previous post on this subject, the pattern matching while transformation introduces a label at the top to continue iteration, a label after the end of the while loop used to stop iteration and resume statements after the while-loop.  The while condition is necessarily reversed because the if-goto at the beginning tests to exit the loop (rather than teesting to continue the while-loop as in C).

Next, let's do the if-goto for the inner while loop:

void bubbleSort(int arr[], int n)
{ 
    int i = 0; // outer for-loop initialization
outerLoopTop:
    if ( i >= n-1 ) goto outerLoopDone;  // exists the outer loop NB: condition reversed!
    int j = 0; 
innerLoopTop:
    if ( j >= n-i-1 ) goto innerLoopDone; // exists the inner loop NB: condition reversed!
    if ( arr [j] > arr [j+1] ) {
        temp = arr [j];
        arr [i] = temp;
        arr [j] = temp;
    }
    j++;
    goto innerLoopTop;
innerLoopDone:
    i++; // outer for-loop increment
    goto outerLoopTop;
outerLoopDone: ;
}

Let's note that the rather mechanical transformations (outer loop to if-goto and inner to if-goto) do not negatively interact with each other and the substitution pattern for the two while-loops could have been applied in either order with ease.

Next, let's transform the if-then statement inside the inner loop into if-goto style.  (Again, let's note that these are relatively simple pattern matching replacements, and, the if-then could have been tranformed to if-goto style before the for-loop transformations, with the same final results.)

void bubbleSort(int arr[], int n)
{ 
    int i, j;
    i = 0; // outer for-loop initialization
outerLoopTop:
    if ( i >= n-1 ) goto outerLoopDone;
    j = 0; // inner for-loop initialization
innerLoopTop:
    if ( j >= n-i-1 ) goto innerLoopDone;
    
    if ( arr [j] <= arr [j+1] ) goto skipSwap; // conditionally skips the then-part NB: condition reversed!
    temp = arr [j];
    arr [i] = temp;
    arr [j] = temp;
skipSwap:               // <--- join point here from the if-then 
    // at the label above, the if-then is over.
    // this code will execute whether the if-then fires or not
    // simply resuming execution after the if-then

    j++;
    goto innerLoopTop;
innerLoopDone:
    i++; // outer for-loop increment
    goto outerLoopTop;
outerLoopDone: ;
}

The transformation to if-goto style is complete.  Structured statements have been removed — there's no curly braces within body of the function, and, all control flow is in terms of if-goto, goto, and labels.


This post is Copyright (C) 2019, Erik L. Eidt

Discover and read more posts from Erik Eidt
get started