Jumping ..
Jumps can be either short or long. Long jumps are coded on dWord and short jumps are coded on Bytes. As jumps can be either up or down (forward / backward), they are stored as signed values. A short jump can therefore only be 127 octets down or 128 octets up.
A jump can be either direct or indirect. Direct jumps are the ones which are known by the Assembler at compile time. Example:
MyLabel:
; ...
; ...
; ...
jmp MyLabel
At compile time, the Assembler knows where 'MyLabel' will be located in Memory at run time. So, it can directly encode the desired immediate Address.
An indirect call is a call to some location that will be known only at run time. This is what we do, for example when calling for an api after loading a DLL 'by hand'.
Call D$SomeExternalFunction
Unconditional Jumps
This is the simple jmp instruction.
Conditional Jumps
They are all these 'j..' jmps following a comparison (cmp or test). The execution depends on the state of the Flags Register (see also Flags_and_Jcc):
Flags: O S Z P C
Simple Flags tests Instructions:
je / jz . . 1 . .
jne / jnz . . 0 . .
jno 0 . . . .
jnp / jpo . . . 0 .
jnz . 0 . . .
jo 1 . . . .
jp / jpe . . . 1 .
je . 1 . . .
Unsigned Math Instructions:
jb / jnae / jc . . . . 1
jbe / jna . . 1 . 1 (both ZF and CF set on)
jnb / jae / jn . . . . 0
jnbe / ja . . 0 . 0 (both ZF and CF set off)
Signed Math Instructions:
jl / jnge A B . . . (NOT (A=B))
jle / jng A B 1 . . (NOT (A=B)) OR ZF
jnl / jge A B . . . (A=B)
jnle / jg A B 0 . .
Read j as 'jump', e as 'equal', z as 'Empty', n as 'not', o as 'overflow', p as 'parity', a as 'above', c as 'carry', b as 'below', g as 'greater', l as 'lower'
cmp eax &FALSE | jne Error ; Jmp if not Equal.
Error:
Looping instructions
All loop Instructions rely on ecx value (they loop ecx times). All loop Instructions address Short jumps; This is to say that the included code, inside a loop cannot exceed 128 octets. For greater chunks of code, we have to use, for example, dec / cmp / jmp...
loop
Example, storing '0123456789' at MyString:
mov ecx 10
mov edi MyString
mov al '0'
L0: stosb | inc al | loop L0<
Beware that, if ecx value is zero before entering the loop, the chunk of code will be run 0FFFF_FFFF times (!!!!!) because The loop instruction first decrements ecx and only after doing so tests if ecx = 0.
To ensure the ecx is *not* zeroed before entering such a loop with a variable value, we have a particular instruction that does the same as ''cmp ecx 0 | je exit'': This is ''jecxz Exit''.
Loope / loopz
(2 mnemonics, 1 opcode)
Does the same job as loop, but stop looping if ZF if set on (1)
mov esi MyString | mov ecx 100
L0: lodsb
; ...
; ...
; ...
cmp al 0
loope L0< ; loops until ecx = 0 and while al = 0
Loopne / Loopnz
Same as above but with reverse added condition:
mov esi MyString | mov ecx 100
L0: lodsb
; ...
; ...
; ...
cmp al 0
loopne L0< ; loops until ecx = 0 and while al <> 0
Sub Routines Instructions
Call
Call is a jumping instruction that pushes the Address following the call onto the Stack before jumping. It is bound to:
Ret
... which pops the return Address and jumps back to it. ret may be followed by an immediate argument telling how many more bytes are to be stripped from the Stack. Useful for HLL organization of sub Routines with Parameters pushed onto the Stack before the call and the Stack being cleared by the callee.
ret 12 ; pops 3 dWords from the Stack and returns to caller.
~~~~~~~