7.7: Control Instructions
- Page ID
- 55762
\( \newcommand{\vecs}[1]{\overset { \scriptstyle \rightharpoonup} {\mathbf{#1}} } \)
\( \newcommand{\vecd}[1]{\overset{-\!-\!\rightharpoonup}{\vphantom{a}\smash {#1}}} \)
\( \newcommand{\id}{\mathrm{id}}\) \( \newcommand{\Span}{\mathrm{span}}\)
( \newcommand{\kernel}{\mathrm{null}\,}\) \( \newcommand{\range}{\mathrm{range}\,}\)
\( \newcommand{\RealPart}{\mathrm{Re}}\) \( \newcommand{\ImaginaryPart}{\mathrm{Im}}\)
\( \newcommand{\Argument}{\mathrm{Arg}}\) \( \newcommand{\norm}[1]{\| #1 \|}\)
\( \newcommand{\inner}[2]{\langle #1, #2 \rangle}\)
\( \newcommand{\Span}{\mathrm{span}}\)
\( \newcommand{\id}{\mathrm{id}}\)
\( \newcommand{\Span}{\mathrm{span}}\)
\( \newcommand{\kernel}{\mathrm{null}\,}\)
\( \newcommand{\range}{\mathrm{range}\,}\)
\( \newcommand{\RealPart}{\mathrm{Re}}\)
\( \newcommand{\ImaginaryPart}{\mathrm{Im}}\)
\( \newcommand{\Argument}{\mathrm{Arg}}\)
\( \newcommand{\norm}[1]{\| #1 \|}\)
\( \newcommand{\inner}[2]{\langle #1, #2 \rangle}\)
\( \newcommand{\Span}{\mathrm{span}}\) \( \newcommand{\AA}{\unicode[.8,0]{x212B}}\)
\( \newcommand{\vectorA}[1]{\vec{#1}} % arrow\)
\( \newcommand{\vectorAt}[1]{\vec{\text{#1}}} % arrow\)
\( \newcommand{\vectorB}[1]{\overset { \scriptstyle \rightharpoonup} {\mathbf{#1}} } \)
\( \newcommand{\vectorC}[1]{\textbf{#1}} \)
\( \newcommand{\vectorD}[1]{\overrightarrow{#1}} \)
\( \newcommand{\vectorDt}[1]{\overrightarrow{\text{#1}}} \)
\( \newcommand{\vectE}[1]{\overset{-\!-\!\rightharpoonup}{\vphantom{a}\smash{\mathbf {#1}}}} \)
\( \newcommand{\vecs}[1]{\overset { \scriptstyle \rightharpoonup} {\mathbf{#1}} } \)
\( \newcommand{\vecd}[1]{\overset{-\!-\!\rightharpoonup}{\vphantom{a}\smash {#1}}} \)
\(\newcommand{\avec}{\mathbf a}\) \(\newcommand{\bvec}{\mathbf b}\) \(\newcommand{\cvec}{\mathbf c}\) \(\newcommand{\dvec}{\mathbf d}\) \(\newcommand{\dtil}{\widetilde{\mathbf d}}\) \(\newcommand{\evec}{\mathbf e}\) \(\newcommand{\fvec}{\mathbf f}\) \(\newcommand{\nvec}{\mathbf n}\) \(\newcommand{\pvec}{\mathbf p}\) \(\newcommand{\qvec}{\mathbf q}\) \(\newcommand{\svec}{\mathbf s}\) \(\newcommand{\tvec}{\mathbf t}\) \(\newcommand{\uvec}{\mathbf u}\) \(\newcommand{\vvec}{\mathbf v}\) \(\newcommand{\wvec}{\mathbf w}\) \(\newcommand{\xvec}{\mathbf x}\) \(\newcommand{\yvec}{\mathbf y}\) \(\newcommand{\zvec}{\mathbf z}\) \(\newcommand{\rvec}{\mathbf r}\) \(\newcommand{\mvec}{\mathbf m}\) \(\newcommand{\zerovec}{\mathbf 0}\) \(\newcommand{\onevec}{\mathbf 1}\) \(\newcommand{\real}{\mathbb R}\) \(\newcommand{\twovec}[2]{\left[\begin{array}{r}#1 \\ #2 \end{array}\right]}\) \(\newcommand{\ctwovec}[2]{\left[\begin{array}{c}#1 \\ #2 \end{array}\right]}\) \(\newcommand{\threevec}[3]{\left[\begin{array}{r}#1 \\ #2 \\ #3 \end{array}\right]}\) \(\newcommand{\cthreevec}[3]{\left[\begin{array}{c}#1 \\ #2 \\ #3 \end{array}\right]}\) \(\newcommand{\fourvec}[4]{\left[\begin{array}{r}#1 \\ #2 \\ #3 \\ #4 \end{array}\right]}\) \(\newcommand{\cfourvec}[4]{\left[\begin{array}{c}#1 \\ #2 \\ #3 \\ #4 \end{array}\right]}\) \(\newcommand{\fivevec}[5]{\left[\begin{array}{r}#1 \\ #2 \\ #3 \\ #4 \\ #5 \\ \end{array}\right]}\) \(\newcommand{\cfivevec}[5]{\left[\begin{array}{c}#1 \\ #2 \\ #3 \\ #4 \\ #5 \\ \end{array}\right]}\) \(\newcommand{\mattwo}[4]{\left[\begin{array}{rr}#1 \amp #2 \\ #3 \amp #4 \\ \end{array}\right]}\) \(\newcommand{\laspan}[1]{\text{Span}\{#1\}}\) \(\newcommand{\bcal}{\cal B}\) \(\newcommand{\ccal}{\cal C}\) \(\newcommand{\scal}{\cal S}\) \(\newcommand{\wcal}{\cal W}\) \(\newcommand{\ecal}{\cal E}\) \(\newcommand{\coords}[2]{\left\{#1\right\}_{#2}}\) \(\newcommand{\gray}[1]{\color{gray}{#1}}\) \(\newcommand{\lgray}[1]{\color{lightgray}{#1}}\) \(\newcommand{\rank}{\operatorname{rank}}\) \(\newcommand{\row}{\text{Row}}\) \(\newcommand{\col}{\text{Col}}\) \(\renewcommand{\row}{\text{Row}}\) \(\newcommand{\nul}{\text{Nul}}\) \(\newcommand{\var}{\text{Var}}\) \(\newcommand{\corr}{\text{corr}}\) \(\newcommand{\len}[1]{\left|#1\right|}\) \(\newcommand{\bbar}{\overline{\bvec}}\) \(\newcommand{\bhat}{\widehat{\bvec}}\) \(\newcommand{\bperp}{\bvec^\perp}\) \(\newcommand{\xhat}{\widehat{\xvec}}\) \(\newcommand{\vhat}{\widehat{\vvec}}\) \(\newcommand{\uhat}{\widehat{\uvec}}\) \(\newcommand{\what}{\widehat{\wvec}}\) \(\newcommand{\Sighat}{\widehat{\Sigma}}\) \(\newcommand{\lt}{<}\) \(\newcommand{\gt}{>}\) \(\newcommand{\amp}{&}\) \(\definecolor{fillinmathshade}{gray}{0.9}\)Program control refers to basic programming structures such as IF statements and looping.
All of the high-level language control structures must be performed with the limited assembly language control structures. For example, an IF-THEN-ELSE statement does not exist at the assembly language level. Assembly language provides an unconditional branch (or jump) and a conditional branch or an IF statement that will jump to a target label or not jump.
The control instructions refer to unconditional and conditional jumping. Jumping is required for basic conditional statements (i.e., IF statements) and looping.
Labels
A program label is the target, or a location to jump to, for control statements. For example, the start of a loop might be marked with a label such as “loopStart”. The code may be re-executed by jumping to the label.
Generally, a label starts with a letter, followed by letters, numbers, or symbols (limited to “_”), terminated with a colon (“:”). It is possible to start labels with non-letter characters (i.e., digits, “_”, “$”, “#”, “@”, “~” or “?”) . However, these typically convey special meaning and, in general, should not be used by programmers. Labels in yasm are case sensitive.
For example,
loopStart: last:
are valid labels. Program labels may be defined only once. The following sections describe how labels are used.
Unconditional Control Instructions
The unconditional instruction provides an unconditional jump to a specific location in the program denoted with a program label. The target label must be defined exactly once and accessible and within scope from the originating jump instruction.
The unconditional jump instruction is summarized as follows:
Instruction |
Explanation |
jmp <label> |
Jump to specified label. |
Examples: |
jmp startLoop jmp ifDone jmp last |
/>Conditional Control Instructions
A more complete list of the instructions is located in Appendix B.
The conditional control instructions provide a conditional jump based on a comparison. This provides the functionality of a basic IF statement.
Two steps are required for a comparison; the compare instruction and the conditional jump instruction. The conditional jump instruction will jump or not jump to the
provided label based on the result of the previous comparison operation. The compare instruction will compare two operands and store the results of the comparison in the rFlag registers. The conditional jump instruction will act (jump or not jump) based on the contents of the rFlag register. This requires that the compare instruction is immediately followed by the conditional jump instruction. If other instructions are placed between the compare and conditional jump, the rFlag register will be altered and the conditional jump may not reflect the correct condition.
The general form of the compare instruction is:
cmp <op1>, <op2>
Where <op1> and <op2> are not changed and must be of the same size. Either, but not both, may be a memory operand. The <op1> operand cannot be an immediate, but the <op2> operand may be an immediate value.
The conditional control instructions include the jump equal (je) and jump not equal (jne) which work the same for both signed and unsigned data.
The signed conditional control instructions include the basic set of comparison operations; jump less than (jl), jump less than or equal (jle), jump greater than (jg), and jump greater than or equal (jge).
The unsigned conditional control instructions include the basic set of comparison operations; jump below than (jb), jump below or equal (jbe), jump above than (ja), and jump above or equal (jae).
The general form of the signed conditional instructions along with an explanatory comment are as follows:
Page 110
je <label> ; if <op1> == <op2> jne <label> ; if <op1> != <op2> jl <label> ; signed, if <op1> < <op2> jle <label> ; signed, if <op1> <= <op2> jg <label> ; signed, if <op1> > <op2> jge <label> ; signed, if <op1> >= <op2> jb <label> ; unsigned, if <op1> < <op2> jbe <label> ; unsigned, if <op1> <= <op2> ja <label> ; unsigned, if <op1> > <op2> jae <label> ; unsigned, if <op1> >= <op2>
For example, given the following pseudo-code for signed data:
if (currNum > myMax) myMax = currNum;
And, assuming the following data declarations:
currNum dq 0 myMax dq 0
Assuming that the values are updating appropriately within the program (not shown), the following instructions could be used:
mov rax, qword [currNum] cmp rax, qword [myMax] ; if currNum <= myMax jle notNewMax ; skip set new max mov qword [myMax], rax notNewMax:
Note that the logic for the IF statement has been reversed. The compare and conditional jump provide functionality for jump or not jump. As such, if the condition from the original IF statement is false, the code must not be executed. Thus, when false, in order to skip the execution, the conditional jump will jump to the target label immediately following the code to be skipped (not executed). While there is only one line in this example, there can be many lines of code.
A more complex example might be as follows:
if (x != 0) { ans = x / y; errFlg = FALSE; } else { ans = 0; errFlg = TRUE; }
This basic compare and conditional jump do not provide a typical IF-ELSE structure. It must be created. Assuming the x and y variables are signed double-words that will be set during the program execution, and the following declarations:
TRUE equ 1 FALSE equ 0 x dd 0 y dd 0 ans dd 0 errFlg db FALSE
The following code could be used to implement the above IF-ELSE statement.
cmp dword [x], 0 ; if statement je doElse mov eax, dword [x] cdq idiv dword [y] mov dword [ans], eax mov byte [errFlg], FALSE jmp skpElse doElse: mov dword [ans], 0 mov byte [errFlg], TRUE skpElse:
In this example, since the data was signed, a signed division (idiv) and the appropriate conversion (cdq in this case) were required. It should also be noted that the edx register was overwritten even though it did not appear explicitly. If a value was previously placed in edx (or rdx), it has been altered.
Range
The target label is referred to as a short-jump. Specifically, that means the target label must be within 128 bytes from the conditional jump instruction. While this limit is not typically a problem, for very large loops, the assembler may generate an error referring to “jump out-of-range”. The unconditional jump (jmp) is not limited in range. If a “jump out-of-range” is generated, it can be eliminated by reversing the logic and using an unconditional jump for the long jump. For example, the following code:
cmp rcx, 0 jne startOfLoop
might generate a “jump out-of-range” assembler error if the label, startOfLoop, is a long distance away. The error can be eliminated with the following code:
cmp rcx, 0 je endOfLoop jmp startOfLoop endOfLoop:
Which accomplishes the same thing using an unconditional jump for the long jump and adding a conditional jump to a very close label.
The conditional jump instructions are summarized as follows:
Instruction |
Explanation |
cmp <op1>, <op2> |
Compare <op1> with <op2>. |
Examples: |
cmp rax, 5 cmp ecx, edx cmp ax, word [wNum] |
je <label> |
Based on preceding comparison instruction, jump to <label> if <op1> == <op2>. |
Examples: |
cmp rax, 5 je wasEqual |
jne <label> |
Based on preceding comparison instruction, jump to <label> if <op1> != <op2>. |
Examples: |
cmp rax, 5 jne wasNotEqual |
jl <label> |
For signed data, based on preceding comparison instruction, jump to <label> if <op1> < <op2>. |
Examples: |
cmp rax, 5 jl wasLess |
jle <label> |
For signed data, based on preceding comparison instruction, jump to <label> if <op1> <op2>. |
Examples: |
cmp rax, 5 jle wasLessOrEqual |
jg <label> |
For signed data, based on preceding comparison instruction, jump to <label> if <op1> > <op2>. |
Examples: |
cmp rax, 5 jg wasGreater |
jge <label> |
For signed data, based on preceding comparison instruction, jump to <label> if <op1> <op2>. |
Examples: |
cmp rax, 5 jge wasGreaterOrEqual |
jb <label> |
For unsigned data, based on preceding comparison instruction, jump to <label> if <op1> < <op2>. |
Examples: |
cmp rax, 5 jb wasLess |
jbe <label> |
For unsigned data, based on preceding comparison instruction, jump to <label> if <op1> <op2>. |
Examples: |
cmp rax, 5 jbe wasLessOrEqual |
ja <label> |
For unsigned data, based on preceding comparison instruction, jump to <label> if <op1> > <op2>. |
Examples: |
cmp rax, 5 ja wasGreater |
jae <label> |
For unsigned data, based on preceding comparison instruction, jump to <label> if <op1> <op2>. |
Examples: |
cmp rax, 5 jae wasGreaterOrEqual |
A more complete list of the instructions is located in Appendix B.
Iteration
The basic control instructions outlined provide a means to iterate or loop.
A basic loop can be implemented consisting of a counter which is checked at either the bottom or top of a loop with a compare and conditional jump.
For example, assuming the following declarations:
lpCnt dq 15 sum dq 0
The following code would sum the odd integers from 1 to 30:
mov rcx, qword [lpCnt] ; loop counter mov rax, 1 ; odd integer counter sumLoop: add qword [sum], rax ; sum current odd integer add rax, 2 ; set next odd integer dec rcx ; decrement loop counter cmp rcx, 0 jne sumLoop
This is just one of many different ways to accomplish the odd integer summation task. In this example, rcx was used as a loop counter and rax was used for the current odd integer (appropriately initialized to 1 and incremented by 2).
The process shown using rcx as a counter is useful when looping a predetermined number of times. There is a special instruction, loop, provides looping support.
The general format is as follows:
loop <label>
Which will perform the decrement of the rcx register, comparison to 0, and jump to the
specified label if rcx ≠ 0. The label must be defined exactly once.
As such, the loop instruction provides the same functionality as the three lines of code
from the previous example program. The following sets of code are equivalent:
Code Set 1 Code Set 2 loop <label> dec rcx cmp rcx, 0 jne <label>
For example, the previous program can be written as follows:
mov rcx, qword [maxN] ; loop counter mov rax, 1 ; odd integer counter sumLoop: add qword [sum], rax ; sum current odd integer add rax, 2 ; set next odd integer loop sumLoop
Both code examples produce the exact same result in the same manner.
Since the rcx register is decremented and then checked, forgetting to set the rcx register could result in looping an unknown number of times. This is likely to generate an error during the loop execution, which can be very misleading when debugging.
The loop instruction can be useful when coding, but it is limited to the rcx register and to counting down. If nesting loops are required, the use of a loop instruction for both the inner and outer loop can cause a conflict unless additional actions are taken (i.e., save/restore rcx register as required for inner loop).
While some of the programming examples in this text will use the loop instruction, it is not required.
The loop instruction is summarized as follows:
Instruction |
Explanation |
loop <label> |
Decrement rcx register and jump to <label> if rcx is ≠ 0. |
Examples: |
loop startLoop loop ifDone loop sumLoop |
A more complete list of the instructions is located in Appendix B.