Instructions of this group make it possible to easily branch the execution, whether in accordance to a specific condition designated by the EFlags/RFlags register or completely unconditionally, and may, therefore, be divided into two groups:
- Unconditional execution flow transfer instructions:
- JMP: Perform unconditional jump to an explicitly specified location. This loads the instruction pointer register with the address of the specified location.
- CALL: This instruction is used to call a procedure. This pushes the address of the next instruction onto the stack and loads the instruction pointer with the address of the first instruction in the called procedure.
- RET: This instruction performs a return from procedure. It pops the value stored on the stack into the instruction pointer register. When used at the end of a procedure, it returns the execution to instruction following the CALL instruction.
The RET instruction may have a two-bytes value as its operand, in which case the value defines the amount of bytes occupied by the operands that were passed to the procedure on stack. The stack pointer is then automatically adjusted by adding the amount of bytes. - INT: This instruction causes a software interrupt.
The use of this instruction on Windows while programming in ring 3 is quite rare. It may even be safe to assume that the only usage is INT3--software breakpoint. On 32-bit Linux, however, it is used for invocation of system calls.
- Conditional execution flow transfer instructions:
- Jcc: This is the conditional variant of the JMP instruction, where cc stands for condition code, which may be one of the condition codes listed in the preceding table. For example, look at the jz .noxor line from the CRC8 example.
- JCXZ: This is a special version of the conditional jump instruction, which uses the CX register as a condition. The jump is only executed if the CX register contains 0.
- JECXZ: This is the same as above, but it operates on the ECX register.
- JRCXZ: This is the same as above, but it operates on the RCX register (long mode only).
- LOOP: A loop with ECX as a counter, this decrements ECX and, if the result is not 0, loads the instruction pointer register with the address of the loop label. We have already used this instruction in the CRC8 example.
- LOOPZ/LOOPE: This is the loop with ECX as a counter while ZF = 1.
- LOOPNZ/LOOPNE: This is the loop with ECX as a counter while ZF = 0.
Let's, for the sake of example, implement the CRC8 algorithm as a procedure (insert the following into the code section of the relevant 32-bit template):
;
; Put your code here
;
mov al, 0x16 ; In this specific case we pass the
; only argument via AL register
call crc_proc ; Call the 'crc_proc' procedure
; For Windows
push 0 ; Terminate the process if you are on Windows
call [exitProcess]
; For Linux ; Terminate the process if you are on Linux
xor ebx, ebx
mov eax, ebx
inc eax
int 0x80
crc_proc: ; Our CRC8 procedure
push ebx ecx edx ; Save the register we are going to use on stack
xor dl, dl ; Initialise the CRC state register
mov ecx, 8 ; Setup counter
.crc_loop:
shl al, 1
setc bl
shl dl, 1
setc bh
xor bl, bh
jz .noxor
xor dl, 0x31
.noxor:
loop .crc_loop
mov al, dl ; Setup return value
pop edx ecx ebx ; Restore registers
ret ; Return from this procedure