X86 Assembly/Control Flow
< X86 AssemblyAlmost all programming languages have the ability to change the order in which statements are evaluated, and assembly is no exception. The instruction pointer (EIP) register contains the address of the next instruction to be executed. To change the flow of control, the programmer must be able to modify the value of EIP. This is where control flow functions come in.
mov eip, label ; wrong
jmp label ; right
Comparison Instructions
test arg1, arg2 | GAS Syntax |
test arg2, arg1 | Intel syntax |
Performs a bit-wise logical AND on arg1
and arg2
the result of which we will refer to as Temp
and sets the ZF
(zero), SF
(sign) and PF
(parity) flags based on Temp
. Temp
is then discarded.
Operands
arg1
- Register
- Immediate
arg2
-
AL/AX/EAX
(only if arg1 is immediate) - Register
- Memory
Modified flags
-
SF
= MostSignificantBit(Temp
) - If (
Temp
== 0)ZF
= 1 elseZF
= 0 -
PF
= BitWiseXorNor(Temp
[Max-1:0]) -
CF
= 0 -
OF
= 0 -
AF
is undefined
cmp arg2, arg1 | GAS Syntax |
cmp arg1, arg2 | Intel syntax |
Performs a comparison operation between arg1
and arg2
. The comparison is performed by a (signed) subtraction of arg2
from arg1
, the results of which can be called Temp
. Temp
is then discarded. If arg2
is an immediate value it will be sign extended to the length of arg1
. The EFLAGS
register is set in the same manner as a sub
instruction.
Note that the GAS/AT&T syntax can be rather confusing, as for example cmp $0, %rax
followed by jl branch
will branch if %rax < 0
(and not the opposite as might be expected from the order of the operands).
Operands
arg1
-
AL/AX/EAX
(only if arg2 is immediate) - Register
- Memory
arg2
- Register
- Immediate
- Memory
Modified flags
-
SF
= MostSignificantBit(Temp
) - If (
Temp
== 0)ZF
= 1 elseZF
= 0 -
PF
= BitWiseXorNor(Temp
[Max-1:0]) -
CF
,OF
andAF
Jump Instructions
The jump instructions allow the programmer to (indirectly) set the value of the EIP register. The location passed as the argument is usually a label. The first instruction executed after the jump is the instruction immediately following the label. All of the jump instructions, with the exception of jmp
, are conditional jumps, meaning that program flow is diverted only if a condition is true. These instructions are often used after a comparison instruction (see above), but since many other instructions set flags, this order is not required.
See X86_Assembly/X86_Architecture#EFLAGS_Register for more information about the flags and their meaning.
Unconditional Jumps
jmp loc
Loads EIP with the specified address (i.e. the next instruction executed will be the one specified by jmp).
Jump if Equal
je loc
ZF = 1
Loads EIP with the specified address, if operands of previous CMP instruction are equal. For example:
mov $5, ecx
mov $5, edx
cmp ecx, edx
je equal
; if it did not jump to the label equal, then this means ecx and edx are not equal.
equal:
; if it jumped here, then this means ecx and edx are equal
Jump if Not Equal
jne loc
ZF = 0
Loads EIP with the specified address, if operands of previous CMP instruction are not equal.
Jump if Greater
jg loc
SF = OF and ZF = 0
Loads EIP with the specified address, if first operand of previous CMP instruction is greater than the second (performs signed comparison).
Jump if Greater or Equal
jge loc
SF = OF or ZF = 1
Loads EIP with the specified address, if first operand of previous CMP instruction is greater than or equal to the second (performs signed comparison).
Jump if Greater (unsigned comparison)
ja loc
CF = 0 and ZF = 0
Loads EIP with the specified address, if first operand of previous CMP instruction is greater than the second. ja
is the same as jg
, except that it performs an unsigned comparison.
Jump if Greater or Equal (unsigned comparison)
jae loc
CF = 0 or ZF = 1
Loads EIP with the specified address, if first operand of previous CMP instruction is greater than or equal to the second. jae
is the same as jge
, except that it performs an unsigned comparison.
Jump if Lesser
jl loc
The criteria required for a JL
is that SF <> OF
, loads EIP with the specified address, if the criteria is meet. So either SF
or OF
can be set but not both in order to satisfy this criteria. If we take the SUB
(which is basically what a CMP
does) instruction as an example, we have:
arg2
-arg1
With respect to SUB
and CMP
there are several cases that fulfill this criteria:
arg2 < arg1
and the operation does not have overflowarg2 > arg1
and the operation has an overflow
In case 1) SF
will be set but not OF
and in case 2) OF
will be set but not SF
since the overflow will reset the most significant bit to zero and thus preventing SF
being set. The SF <> OF
criteria avoids the cases where:
arg2 > arg1
and the operation does not have overflowarg2 < arg1
and the operation has an overflowarg2 == arg1
In case 1) neither SF
nor OF
are set, in case 2) OF
will be set and SF
will be set since the overflow will reset the most significant bit to one and in case 3) neither SF
nor OF
will be set.
Jump if Less or Equal
jle loc
SF <> OF
or ZF = 1
.
Loads EIP with the specified address, if first operand of previous CMP instruction is lesser than or equal to the second. See the JL
section for a more detailed description of the criteria.
Jump if Lesser (unsigned comparison)
jb loc
CF = 1
Loads EIP with the specified address, if first operand of previous CMP instruction is lesser than the second. jb
is the same as jl
, except that it performs an unsigned comparison.
Jump if Lesser or Equal (unsigned comparison)
jbe loc
CF = 1 or ZF = 1
Loads EIP with the specified address, if first operand of previous CMP instruction is lesser than or equal to the second. jbe
is the same as jle
, except that it performs an unsigned comparison.
Jump if Overflow
jo loc
OF = 1
Loads EIP with the specified address, if the overflow bit is set on a previous arithmetic expression.
Jump if Not Overflow
jno loc
OF = 0
Loads EIP with the specified address, if the overflow bit is not set on a previous arithmetic expression.
Jump if Zero
jz loc
ZF = 1
Loads EIP with the specified address, if the zero bit is set from a previous arithmetic expression. jz
is identical to je
.
Jump if Not Zero
jnz loc
ZF = 0
Loads EIP with the specified address, if the zero bit is not set from a previous arithmetic expression. jnz
is identical to jne
.
Jump if Signed
js loc
SF = 1
Loads EIP with the specified address, if the sign bit is set from a previous arithmetic expression.
Jump if Not Signed
jns loc
SF = 0
Loads EIP with the specified address, if the sign bit is not set from a previous arithmetic expression.
Function Calls
call proc
Pushes the address of the next opcode onto the top of the stack, and jumps to the specified location. This is used mostly for subroutines.
ret [val]
Loads the next value on the stack into EIP, and then pops the specified number of bytes off the stack. If val is not supplied, the instruction will not pop any values off the stack after returning.
Loop Instructions
loop arg
The loop
instruction decrements ECX and jumps to the address specified by arg
unless decrementing ECX caused its value to become zero. For example:
mov ecx, 5
start_loop:
; the code here would be executed 5 times
loop start_loop
loop
does not set any flags.
loopx arg
These loop instructions decrement ECX and jump to the address specified by arg
if their condition is satisfied (that is, a specific flag is set), unless decrementing ECX caused its value to become zero.
loope
loop if equalloopne
loop if not equalloopnz
loop if not zeroloopz
loop if zero
Enter and Leave
enter arg
Creates a stack frame with the specified amount of space allocated on the stack.
leave
destroys the current stack frame, and restores the previous frame. Using Intel syntax this is equivalent to:
mov esp, ebp
pop ebp
This will set EBP
and ESP
to their respective value before the function prologue began therefore reversing any modification to the stack that took place during the prologue.
Other Control Instructions
hlt
Halts the processor. Execution will be resumed after processing next hardware interrupt, unless IF is cleared.
nop
No operation. This instruction doesn't do anything, but wastes an instruction cycle in the processor. This instruction is often represented as an XCHG operation with the operands EAX and EAX.
lock
Asserts #LOCK prefix on next instruction.
wait
Waits for the FPU to finish its last calculation.