Assembly Language Conditionals and Loops
Motivation
To look at the various loop structures and conditional control structures; and have an understanding how they are implemented in assembly language.
Introduction
When working with control structures and loops in assembly language, the concepts are not much different than when working with them
in high level languages. As with all aspects of assembly language, we are dealing with these same high level ideas at a much lower level. We
have loops, and conditional control_structures to use just as in high level languages.
- loops::= for | for_increment | for_decrement | pre_test | post_test loops
- control_structures::= if | if_else | if_elseif_else | switch_case
- for::= for some_index = low to high, some_index iterates from low to high incrementing by one each iteration until some_value is greater than
high, see the following for an assembly language example in NASM:
mov rcx, low ; rcx register commonly used for index counter
lp: ... ; statements inside for loop
inc rcx ; increment index by one
cmp rcx, high ; compare rcx to high
jle lp ; jump if less than or equal to lp (lp can be whatever loop label you want)
... ; code after the for loop
- for_increment::= for some_index = low to high step increment, some_index iterates from low to high incrementing by increment value
each iteration until some_value is greater than high, see the following for an assembly language example in NASM:
mov rcx, low ; rcx register commonly used for index counter
lp: ... ; statements inside for loop
add rcx, increment ; increment index by one
cmp rcx, high ; compare rcx to high
jle lp ; jump if less than or equal to lp (lp can be whatever loop label you want)
... ; code after the for loop
- for_decrement::= for some_index = high to low step decrement, some_index iterates from high to low decrementing by decrement value
each iteration until some_value is less than low, see the following for an assembly language example in NASM:
mov rcx, high ; rcx register commonly used for index counter
lp: ... ; statements inside for loop
add rcx, decrement ; increment index by one - use add if decrement is a negative value, sub if decrement is positive
cmp rcx, low ; compare rcx to high
jge lp ; jump if greater than or equal to lp (lp can be whatever loop label you want)
... ; code after the for loop
- pre_test::= high level loop construct, in which we test for a test condition before executing the code block inside the loop,
looping whilest the condition is true. In assembly language, we could have the following for a pre-test loop:
mov rcx, some_value
lp: cmp rcx, test_value ; do our pre_test for some value to be less than test_value
jg ext ; jump to label ext (exit) if greater than test_value
... ; code to execute when some_value is less than test_value
inc rcx ; increment rcx, we could use an add rcx, increment value if increment is more than one
jmp lp ; jump back to lp - this is okay until we get into superscalar programming, then it can be iffy...
ext: ... ; code to execute after pre-test loop done
- post_test::= high level loop construct, in which we test for a test condition after executing the code block inside the loop,
looping whilest the condition is true. In assembly language, we could have the following for a post-test loop:
mov rcx, some_value
lp: ... ; code to execute when some_value is less than test_value
... ; code to execute when some_value is less than test_value
inc rcx ; increment rcx, we could use an add rcx, increment value if increment is more than one
cmp rcx, test_value ; do our pre_test for some value to be less than test_value
jle lp ; jump to label lp if less than or equal to test_value
... ; code to execute after pre-test loop done
- if::= if a condition is true, execute code block. In assembly language:
cmp {reg|mem}, some_value ; compare a register or memory location with some_value
j_cc ext ; jump to ext when condition code is evaluated to false
... ; code to execute when comparision and condition code are true
ext: ... ; code to continue after if block
- if_else::= if a condition is true, execute code block; else execute block for when condition is false. In assembly language:
cmp {reg|mem}, some_value ; compare a register or memory location with some_value
j_cc fls ; jump to fls when condition code is evaluated to false
... ; code to execute when comparision and condition code are true
jmp ext ; jump over the false block (label with fls) to ext
fls: ... ; code to execute if condition is false
...
ext: ... ; code to continue after if/else blocks
- if_elseif_else::= if a condition is true, execute code, else if another condition is true, execute second code block, continuing with
as many chained if conditions being true, followed by a closing else if all previous conditions are false. In assembly language:
cmp {reg|mem}, some_value ; compare a register or memory location with some_value
j_cc c1 ; jump to fls when condition code is evaluated to false
... ; code to execute when comparision and condition code are true
jmp ext ; jump over the false block (label with fls) to ext
c1: cmp {reg|mem}, some_value2 ; compare a register or memory location with some_value
j_cc c2 ; jump to fls when condition code is evaluated to false
...
jmp ext
c2: cmp {reg|mem}, some_value3 ; compare a register or memory location with some_value
j_cc fls ; jump to fls when condition code is evaluated to false
...
jmp ext
fls: ... ; code when all conditions are false
ext: ... ; code to continue after if/else blocks
- switch_case::= test for different values of a variable, in assembly language {reg|mem} is the same variable through out the
code block:
cmp {reg|mem}, value1 ; switch variable value in reg or memory, same reg/memory location through out entire block
jg c2 ; test case #2 if greater than, a jne would not allow us to fall through to next condition
; if needed
... ; code to execute for case #1
[jmp ext] ; this is an optional instruction, if we have a c/c++ style break; keyword, jump to ext, otherwise
; do not jump and have it fall through to the next case
c2: cmp {reg|mem}, value2 ; {reg|mem} same as above, but testing for value2...
jg c3 ; jump to c3 if value2 is smaller than {reg|mem}
...
[jmp ext]
c3: cmp {reg|mem}, value3 ; {reg|mem} same as above, but testing for value3...
jg dft ; jump to default if greater
...
[jmp ext]
dft: ... ; default code block
...
ext: ... ; code after switch block
- branching::= jmp label, j_cc label
- jmp::= jmp label - unconditionally jumps the instruction pointer/program execution to address located at label.
- j_cc::= j_condition_code label - jumps the instruction pointer/program execution to address located at label based on j_condition_code.
- j_condition_code::= jo, jno, jb, jnae, jae, jnb, je, jz, jne, jnz, jbe, jna, ja, jnbe, js, jns,
jp, jpe, jnp, jpo, jl, jnge, jge, jnl, jle, jng, jg, jnle, jcxz, jecxz, jrcxz
- jo::= jo label, jumps to label if overflow (overflow flag set to one)
- jno::= jno label, jumps to label if not overflow (overflow flag set to zero)
- jb::= jb label, jumps to label if below (carry flag set to one), some older disassemblers may disassemble this as jc label
- jnae::= jnae label, jumps to label if not above or equal (carry flag set to one), same as jb.
- jae::= jae label, jumps to label if above or equal (carry flag set to zero), same as jnb.
- jnb::= jnb label, jumps to label if not below (carry flag set to zero), some older disassemblers may disassemble this as jnc label, same
as jae.
- je::= je label, jump to label if equal (zero flag set to one), same as jz
- jz::= jz label, jump to label if zero (zero flag set to one), same as je
- jne::= jne label, jump to label if not equal (zero flag set to zero), same as jnz
- jnz::= jnz label, jump to label if not zero (zero flag set to zero), same as jne
- jbe::= jbe label, jump to label if below or equal (zero flag set to one OR carry flag set to one), same as jna
- jna::= jna label, jump to label if not above (zero flag set to one OR carry flag set to one), same as jbe
- jnbe::= jnbe label, jump to label if not below or equal (zero flag set to zero AND carry flag set to zero), same as ja
- ja::= ja label, jump to label if above (zero flag set to zero AND carry flag set to zero), same as jnbe
- js::= js label, jump to label if sign (sign flag set to one)
- jns::= jns label, jump to label if not sign (sign flag set to zero)
- jp::= jp label, jump to label if parity (parity flag set to one, even parity), same as jpe
- jpe::= jpe label, jump to label if parity even (parity flag set to one), same as jp
- jnp::= jnp label, jump to label if not parity (parity flag set to zero, odd parity), same as jpo
- jpo::= jpo label, jump to label if parity odd (parity flag set to zero), same as jnp
- jl::= jl label, jump to label if less than (sign bit AND overflow bit evaluated to one), same as jnge
- jnge::= jnge label, jump to label if not greater than or equal (sign flag AND overflow flag evaluated to one), same as jl
- jge::= jge label, jump to label if greater than or equal (sign flag is equal to overflow flag), same as jnl
- jnl::= jnl label, jump to label if not less than (sign flag is equal to overflow flag), same as jge
- jle::= jle label, jump to label if less than or equal (zero flag set to one OR (sign flag AND overflow flag evaluated to one)), same as jng
- jng::= jng label, jump to label if not greater than (zero flag set to one OR (sign flag AND overflow flag evaluated to one)), same as jle
- jg::= jg label, jump to label if greater (zero flag set to zero OR sign flag equal to overflow flag), same as jnle
- jnle::= jnle label, jump to label if not less than or equal (zero flag set to zero OR sign flag equal to overflow flag), same as jg
- jcxz::= jcxz label - a very expensive instruction in terms of clock cycles that jumps to label when cx = 0
- jecxz::= jecxz label - a very expensive instruction in terms of clock cycles that jumps to label when ecx = 0
- jrcxz::= jecxz label - a very expensive instruction in terms of clock cycles that jumps to label when rcx = 0
. . . . . . . . . ( end of section Assembly Language Conditionals and Loops) <<Contents | Index>>