Branching

Using Unconditional and Conditional Jumps




Welcome

Hi! Welcome to the sixth chapter of this series. Now, I'd like to explain about how can we do jumps, conditionally or unconditionally. Conditional jumps always consider some condition. If the condition is satisfied, then the jump is taken, otherwise it is not. The conditions are usually reflected in the processor flags. This may be confusing at first. So, I'll take a different approach so that you, that are more familiar with higher level language, can quickly absorb the idea. This conditional jumps is basically like an if construct by large.

On the other hand, unconditional jumps do not regard any conditions. So, it is more like gotos in a sense. In assembly, we can do a more interesting stuffs for sure. But I don't want to explain the bag of clever tricks here at first. I'm covering the basic ones and will reveal more deeper materials later, probably in lesson 2 or so.

 

Making Labels

Labels are essential to jump instructions. It marks the destination. Of course you need to set where to jump, don't you? ;-) Making labels in assembly are easy. Perhaps I already explained this in chapter 1, but let me reclarify this once more. Labels can be made like this:

   example:

So, we can pick out any names and stick a colon after it (:). Voila! That's it. You must make sure that all label names throughout your programs are unique, no duplicates. This limitation will be lifted up when you know subroutines though. I'll explain this later. For now, let's just follow the uniqueness rule, OK?

 

Unconditional Jumps

Syntax of jump instructions are the same. It usually takes form of jump_instr dest_label and of course we have lots of different jump instructions in Intel x86 processors. For unconditional jump, the instruction is jmp. For example:

            jmp   somewhere
             :
             :
 somewhere: ; it will continue here

As mentined earlier, unconditional jumps takes no regard on conditions. So, whenever the processor arrives at the instruction jmp somewhere, it will directly skip all the instructions below it up to until the instruction marked by the label somewhere.

 

Conditional Jumps

Conditional jumps are just verisimilar. However, before the jump instruction, we (usually) have to put a comparison or testing instruction. The comparison instruction I'm going to introduce here is cmp. As I already mention, the conditional jump is analoguous to an if construct. So, I'm going to explain it this way. Look at the following example:

 
AssemblyC/C++/Java EquivalentPascal Equivalent
    cmp   ax, bx
    jg    isgreater
       :
       :   ; block 1  (else part)
       :
    jmp   after
isgreater:
       :
       :   ; block 2  (then part)
       :
after:
       :   ; after if
    if (ax > bx)
    {
        // block 2
    } else
    {
        // block 1
    }
    // after if
    if ax > bx then
    begin
        { block 2 }
    end else
    begin
        { block 1 }
    end
    { after if }

This should be clear enough. You can observe that the cmp instruction above is used to compare ax and bx. The jump instruction is the one that actually does the check. So, the jump instruction used above is jg which means "jump if greater". Other commonly used jump instructions are as follows:

 
InstructionMeaning
jgJump if greater
jgeJump if greater or equal
jlJump if less
jleJump if less or equal
jeJump if equal
jneJump if not equal
jcJump if carry flag is set

Note that jg, jge, jl, and jle will work for signed variables only (i.e. the ones that may have negatives). For unsigned variables, use ja, jae, jb, and jbe as the subtitution respectively. The rest (i.e. je, jne, and jc) work with both signed and unsigned variables. If you're curious about the meaning of ja or jb, they are "jump if above" and "jump if below" respectively.

 

Testing Instruction

Probably you encounter a lot of test instruction when reading assembly programs. It seems that it may replace the functionalify of cmp instruction above since after that it is usually followed by a conditional jump instruction. The answer is: Not quite. Let's look at the syntax of test instruction:

   test x, y

What this instruction do? Well, it behaves like an and but it does not store the result back to x. So it is more like x and y. Usually after this instruction, we usually check whether the result of the and-ing is zero or not using jz or jnz (i.e. "jump if zero").

 

Example 1

Let's try to wrap up with an example. Say, we'd like to add 1+2+3+...+10. The program in C/C++ or Pascal is simple. Let's examine the assembly counterpart:

ideal
p286n
model tiny

codeseg
   org 100h
   jmp start

start:
   mov  cx, 10       ; The counter is in CX
   mov  ax, 0        ; I use AX as a sum holder

myloop:
   add  ax, cx       ; ax = ax + cx
   dec  cx           ; decrement the counter
   cmp  cx, 0        ; is cx zero?
   jne  myloop       ; if not, then loop. If yes, then quit.

quit:
   ; here ax will hold the value of 1+2+...+10


   mov  ax, 4c00h
   int  21h
end

In MASM version:


.286
.model tiny

.code
   org 100h
entry:
   jmp start

   ; your data and subroutine here

start:
   mov  cx, 10       ; The counter is in CX
   mov  ax, 0        ; I use AX as a sum holder

myloop:
   add  ax, cx       ; ax = ax + cx
   dec  cx           ; decrement the counter
   cmp  cx, 0        ; is cx zero?
   jne  myloop       ; if not, then loop. If yes, then quit.

quit:
   ; here ax will hold the value of 1+2+...+10


   mov  ax, 4c00h
   int  21h
end entry

Hopefully the examples above helps you to understand. Of course that example is not optimized and just plain vanilla.

 

Example 2: Factorial

The world of programming tutorials seems incomplete without doing this factorial example. I assume you know what factorial means. Suppose we'd like to calculate 8 factorial. Let's examine the example below:


ideal
p286n
model tiny

codeseg
   org 100h
   jmp start

start:
   mov  cx, 8         ; Again, CX becomes the counter
   mov  ax, 1         ; Since mul instruction uses DX:AX register pair
   mov  dx, 0         ; We use them to hold our factorial product.
                      ; We initially set it to 1
myloop:
   mul  cx            ; DX:AX = AX * CX
   dec  cx            ; decrement counter
   cmp  cx, 0
   jne  myloop

quit:
   ; here DX:AX will hold the value of the factorial

   mov  ax, 4c00h
   int  21h
end

In MASM version:


.286
.model tiny

.code
   org 100h
entry:
   jmp start

   ; your data and subroutine here

start:
   mov  cx, 8         ; Again, CX becomes the counter
   mov  ax, 1         ; Since mul instruction uses DX:AX register pair
   mov  dx, 0         ; We use them to hold our factorial product.
                      ; We initially set it to 1
myloop:
   mul  cx            ; DX:AX = AX * CX
   dec  cx            ; decrement counter
   cmp  cx, 0
   jne  myloop

quit:
   ; here DX:AX will hold the value of the factorial

   mov  ax, 4c00h
   int  21h
end entry

 

Closing

OK, I think that's all for now. Higher assembly level constructs like if, switch (or case..of in Pascal), while, and for are built using these commands. It involves a go to like construct and seems to be a taboo for structured programming approach. Well, that's all we've got. Anyway, jumping around is not that bad. ;-) It's probably better for you to construct higher level programming structure in terms of instructions you've learned so far. However, assembly has a loop instruction too. I'll discuss this on the next chapter. See you next time.

 


Where to go

Chapter 7
News Page
x86 Assembly Lesson 1 index
Contacting Me


Roby Joehanes © 2001