Review of the assembler instructions used in if-statement translation

Assembler construct to compare a variable with a constant:

 cmp  rN, #n  // compares rN with n, setup flags
 blt  label   // If the flags indicate that ( rN < n ) 
              // then branch to label 

 next-instr   // Otherwise, continue here with the "next-instr" 
 ....
 ....

label: 

Assembler construct to compare a variable with a another variable:

 cmp  rN, rM  // compares rN with rM, setup flags
 blt  label   // If the flags indicate that ( rN < rM ) 
              // then branch to label 

 next-instr   // Otherwise, continue here with the "next-instr"
 ....
 ....

label:  

The same explanation applies with the other conditional branch instructions !

Review of the assembler instructions used in if-statement translation
 

We can combinate any one of the 2 compare instructions with any one of the 6 conditional branch instructions:

Combine:

   cmp  rN, #n  // compares rN with n
                // sets the flags according to comparison 
   cmp  rN, rM  // compares rN with rM
                // sets the flags according to comparison

with:

   beq  label   // if ( rN == {n or rM} ) branch to label
   bne  label   // if ( rN != {n or rM} ) branch to label
   blt  label   // if ( rN <  {n or rM} ) branch to label
   ble  label   // if ( rN <= {n or rM} ) branch to label
   bgt  label   // if ( rN >  {n or rM} ) branch to label
   bge  label   // if ( rN >= {n or rM} ) branch to label
   

Furthermore, there is an unconditional branch instruction b label that always branches to the location label.

Background information: a quick course in logic
 

The inverse of the comparison operations:

    Comparison     Inverse        "In other words"
  -----------------------------------------------------  
      x == y        x != y      !(x == y)  x != y
      x != y        x == y	!(x != y)  x == y

      x  < y        x >= y	!(x  < y)  x >= y
      x <= y        x >  y	!(x <= y)  x >  y

      x  > y        x <= y	!(x  > y)  x <= y
      x >= y        x <  y	!(x >= y)  x <  y
   

Reason:

  • We often need to branch when a condistion is false

Order of discussion
 

  • First, we study the programming of the control structures in Assembler:

      • We use only simple int typed variables

      • Translate these if-statements and while-statements into ARM assembler code

  • Later, we study control structures that use data structures:

      1. A for-loop that sums the elements in an array

      2. A while-loop with an if-statement that finds the maximum value stored in a linked list

Program flow of the if-statement
 

                                 Flow chart of the if-statement 

   if ( condition )   ---->            |
   {                                   |
      statement(s);	       	+--------------+  FALSE  
   }				|  condition   |--------+     
				+--------------+	|
				       |		|
				       | TRUE		|
				       |		|
				       V		|
				   statement(s)		|
				       |		|
				       |		|
				       V		|
				       +<---------------+
				       |
				       V
  

How to translate a conditional in assembler

  • Recall how a conditional branch (e.g. beq, bne, blt, ...) is executed:

      • If the branch condition is true, the branch is taken

      • Otherwise, the program will continue with the next instruction (following the conditional branch instruction)


  • How to use a flow chart to write assembler code:

    • The horizontal branch of a conditional in the flow chart is translated as a conditional branch

How a compiler translates an if-statement into assembler code
 

Assembler code that implements the program flow specified by an if-statement:

  Assembler codes to evaluate "condition" (use cmp instruction)
                |
		V				        FALSE     
  Branch on  FALSE outcome of "condition" to label L: ----+
		|					  |
		| (True)                                  |
		|					  |
		V					  |
  Assembler codes to execute "statement(s)"      	  |
		|					  |
		|					  |
		V					  |
    L:		+<----------------------------------------+  
		|
		V
   

I will illustrate the translation process with an example...

Example translating an if-statement

Example if-statement:

   int x;

   if ( x < 0 )
     x = -x;           
   

 

For brevity, I will omit the variable definition from now on
because we have seen such definition many times already...

Example translating an if-statement

If-statement in a high level language:

   if ( x < 0 )
     x = -x;       

The corresponding flow chart for this if-statement is:

The branch condition is NOT ( x < 0 ) ( x >= 0 ) - now translate into assembler !

Example translating an if-statement

main:
   movw    r0, #:lower16:x
   movt    r0, #:upper16:x         // r0 = addr(x)
   ldr     r0, [r0]                // r1 = x

   cmp     r0, #0                  // Compare x against 0

   bge     IfEnd                   // if (x >= 0) skip "x=-x" to ifEnd  

   // x = -x;
   movw    r0, #:lower16:x
   movt    r0, #:upper16:x         // r0 = addr(x)
   ldr     r1, [r0]                // r1 = value in x
   neg     r1, r1                  // r1 = value -x 
   str     r1, [r0]                // Update variable x with the value r0=-x

IfEnd:

        .data
x:      .4byte  -4  // x = -4   -- try +4 also
        .end  

DEMO:   /home/cs255001/demo/asm/6-if/if1.s

Optimized example of the same if-statement

main:
   movw    r0, #:lower16:x
   movt    r0, #:upper16:x         // r0 = addr(x)

   ldr     r1, [r0]                // r1 = x

   cmp     r1, #0                  // Compare x ? 0
   bge     IfEnd                   // Branch to "ifEnd" if  x >= 0 

   // (We don't need to fetch x, since r1 = x !
   neg     r1, r1                  // r1 = 0 - r1 (negate)

   // Note: r0 still contains addr(x) !
   str     r1, [r0]                // Update x with -x in r0
IfEnd:

        .data
x:      .4byte  -4  // x = -4   -- try +4 also
        .end
   

I do not recommend/require that you optimize (because it's more error prone)

Example 2 on tranlating an if-statement (comparing 2 variables)
 

Example 2: making sure that x ≤ y:

   int x;
   int y;
   int help;

   // If-statement to make sure: x ≤ y 
   if ( x > y )   // This is the classic "swap(x,y)" algorithm  
   {
      help = x;
      x = y;
      y = help;
   }
   

Comment:   this if-statement is part of the Bubble Sort algorithm

Example 2 on tranlating an if-statement

   if ( x > y )                 
   {
      help = x;     // Swap x and y
      x = y;
      y = help;
   }   

The corresponding flow chart for this if-statement is:

Note:   in assembler code, you do not need the help variable to swap (use registers instead) !

Example 2 on tranlating an if-statement

main:
        // Test  if ( x > y )
        movw    r0, #:lower16:x
        movt    r0, #:upper16:x         // r0 = addr(x)
        ldr     r0, [r0]                // r0 = x

        movw    r1, #:lower16:y
        movt    r1, #:upper16:y         // r1 = addr(y)
        ldr     r1, [r1]                // r1 = y

        cmp     r0, r1                  // Compare x ? y
        ble     ifEnd                   // Branch if  x <= y to ifEnd

    /* ------------- swap x and y ------------------------ */
        // Get addr x and value in x
        movw    r0, #:lower16:x
        movt    r0, #:upper16:x         // r0 = addr(x)
        ldr     r1, [r0]                // r1 = x

        // Get addr y and value in y
        movw    r2, #:lower16:y
        movt    r2, #:upper16:y         // r2 = addr(y)
        ldr     r3, [r2]                // r3 = y

        str     r3, [r0]                // Update x with the value of y
        str     r1, [r2]                // Update y with the value of x

ifEnd:

/* --------------------------------------------------
   Begin of the permanent program variables
   -------------------------------------------------- */
    .data
x:  .4byte   9   // x = 9   -- try a value smaller that 4
y:  .4byte   4   // y = 4

        .end
   

DEMO:   /home/cs255001/demo/asm/6-if/if2.s

More efficient solution - Example 2 on tranlating an if-statement

main:

    movw    r0, #:lower16:x
    movt    r0, #:upper16:x  // r0 = addr(x)
    ldr     r1, [r0]         // r1 = value of x

    movw    r2, #:lower16:y
    movt    r2, #:upper16:y  // r2 = addr(y)
    ldr     r3, [r2]         // r3 = value of y 

    cmp     r1, r3           // Compare x against y
    ble     ifEnd            // if ( x <= y ) branch to ifEnd

    // Swap x and y using values of x and y in R1 and R3
    str     r3, [r0]         // var x in memory = copy of y in R3
    str     r1, [r2]         // var y in memory = copy of x in R1
ifEnd:

/* --------------------------------------------------
   Begin of the permanent program variables
   -------------------------------------------------- */
    .data
x:  .4byte   9   // x = 9   -- try a value smaller that 4
y:  .4byte   4   // y = 4

        .end  

DEMO:   /home/cs255001/demo/asm/6-if/if3.s