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.
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?
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 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:
Assembly | C/C++/Java Equivalent | Pascal 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:
Instruction | Meaning |
---|---|
jg | Jump if greater |
jge | Jump if greater or equal |
jl | Jump if less |
jle | Jump if less or equal |
je | Jump if equal |
jne | Jump if not equal |
jc | Jump 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.
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").
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.
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
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.
Chapter 7
News Page
x86 Assembly Lesson 1 index
Contacting Me
Roby Joehanes © 2001