CHAPTER 5 - Jumps and branching

You should know a little about how instructions are processed by processor. It fetches instruction in machine code, executes it, and then moves to next instruction. This is repeaten until instruction int 20h is reached. In this chapter we will learn something about instructions which changes this behaviour.

5.1. instruction pointer
Processor loads first instructions (it determines number of bytes the instrution consists from), executes it and then moves to another instruction. But how this mechanism works? Processor has a special word register "ip" which holds address of currently executed instruction. After instruction is executed processor adds it's size to "ip" and executes instruction on address in "ip". Mechanism works like this: NOTE: as with others pointers, ip doesn't hold full address of instruction, only offset part. Be we don't care about this now.

NOTE: "ip" stands for "instruction pointer".

5.2. Jumps
Register ip is not like other registers (like ax, ah,bp...). It's contents can't be changed using mov instruction. mov ip,5 doesn't work. But there is a special instruction which can change value in ip register. It is jmp ("jmp" = "jump") instruction. This instruction has one operand, new address for ip register. So jmp 5 has effect like mov ip,5 would if it were an instruction. Example:
org 256
jmp Start
text db 'Text to output'
mov ah,9
mov dx,text
int 21h
int 20h
First instruction sets value of ip to address of mov ah,9 instruction (address is held in label Start). Thus processor won't try to execute bytes defined by "Text to output" string and this program will work.

NOTE: of course, when ip is changed by jmp instruction, then size of this instruction is NOT added to it.

5.3. Comparing and conditonal jumps
If you can code any language already you should know branching, eg. conditional execution of some parts of code. For example: say you want value not greater than 10 in al. So if value in al register is > 10, you will set al to 10. This is branching - if some condition is true then something is executed, otherwise it is not executed. Assembly impletation of this mechanism is that when condition is false you will jump over conditional code, when condition is true you will just cotinue execution. It is as if C code:
if (condition)
  ConditionalCode(); //this can be any C code, not just function call
would be writen this way:
if (!condition) goto LabelAfterConditionalCode;
ConditionalCode(); //this can be any C code, not just function call
First problem is how to decide whether condition is true. In assembly, there is instruction which can compare two operands. It is cmp. It's operands follow same rules as mov's operands (almost every instruction follows these or very similar rules). So examples of comparing:
cmp ax,bx		      ; compare value of "ax" to value of "bx"
cmp al,byte [SomeLabel]       ; comapre value of "al" to byte at SomeLabel
cmp ax,5		      ; compare value of "ax" to 5
cmp ax,al		      ; wrong, operands have different size
This instructions checks whether first operand is same, greater or lesser than second.
instruction: cmp
OK, we can compare, but how are results of comparison stored? CPU (processor) has special register called "flags register" in which it stores results of comparison (and some other things too). This register can't be accessed with mov or similar instructions (same like ip), it's value is set by cmp instruction. Now you don't have to care HOW is result of comparison stored in this register, you would need understand bit arithmetics.
register: flags
OK, we can compare, we know result is stored in flags. Only thing we need now is conditional jump itslef. Conditional jump is jump which is taken only when condition specified by you is true (in flags register). It will be best explained on example. We compare ax to bx (cmp ax,bx). Now conditional jump can jump if ax < bx, or when ax = bx, or when ax >= bx etc. These jumps are (op1 is first operand of cmp, op2 is second): Example code: (but don't try to compile it, it is not .COM executable, it is just piece of code)
cmp ax,10
jbe AX_lesser_than_10
mov ax,10
this piece of code will check whether value in ax is below or equal to 10, and if not (if the value in ax is above 10) it will set ax to 10. Corresponding C code is:
if (ax>10) ax=10;
or more similar to our assembly version:
if (ax <= 10) goto AX_lesser_than_10
Another example: get maximum of {ax,bx} and store it in ax:
cmp ax,bx
jae AX_already_contains_bigger_value
mov ax,bx
So compare ax to bx, if it is bigger or equal then it already contains the bigger value, we dont need to change anything. If ax is lesser than bx then we must move value in bx (=bigger value) to ax.

More complicated version: store maximum of {ax,bx} in cx:
cmp ax,bx
ja  AX_bigger
mov cx,bx
jmp done
mov cx,ax
so we compare ax to bx, then if ax is lesser than bx jump won't be taken and we continue by mov cx,bx which stores bigger value in cx as wanted, and then jmp done skips instructions used in case ax is bigger. If ax is bigger than bx, then jmp AX_bigger will be taked, so next instruction is mov cx,ax which moves greater value (in ax) to cx. You see, code was divided into two "branches" one for ax>bx, other for ax<=bx. Finally both branches goes to instruction behind done:, and at this place cx always holds bigger value. By the way, there could be jae instead ja, because for case when ax=bx both branches have same effect.
instructions: je, ja, jb, jae, jbe
But what can we do if we want to jump when operands are NOT equal? We could do something like this:
cmp ax,bx
je Same
jmp NotSame
but this is not needed because there are instructions which jumps when condition is not true. These are jne,jna, jnb,jnae and jnbe. Instruction jne jumps when operands are not equal, jna when first operand is not above second operand etc., so:
cmp ax,bx
jne NotSame:
and ... part is executed only if value in ax is equal to value in bx.

NOTE: jna is same as jbe, jnb is same as jae, jb is same as jnae, ja is same as jnbe.
instructions: jne, jna, jnb, jnae, jnbe
NOTE: (important) many instruction change flags register, not only cmp, so conditional jumps should be right behind cmp, no instructions between them.