Skip to main content
Engineering LibreTexts

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}}\)

    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.
    Note, label must be defined exactly once.

    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>.
    Results are stored in the rFlag register. Note 1, operands are not changed.
    Note 2, both operands cannot be memory. Note 3, <op1> operand cannot be an immediate.

    Examples:

    cmp   rax, 5
    cmp   ecx, edx
    cmp   ax, word [wNum]
    
    je <label>

    Based on preceding comparison instruction, jump to <label> if <op1> == <op2>.
    Label must be defined exactly once.

    Examples:

    cmp   rax, 5
    je    wasEqual
    
    jne <label>

    Based on preceding comparison instruction, jump to <label> if <op1> != <op2>.
    Label must be defined exactly once.

    Examples:

    cmp   rax, 5
    jne   wasNotEqual
    
    jl <label>

    For signed data, based on preceding comparison instruction, jump to <label> if <op1> < <op2>.
    Label must be defined exactly once.

    Examples:

    cmp   rax, 5
    jl    wasLess
    
    jle <label>

    For signed data, based on preceding comparison instruction, jump to <label> if <op1> <op2>.
    Label must be defined exactly once.

    Examples:

    cmp   rax, 5
    jle    wasLessOrEqual
    
    jg <label>

    For signed data, based on preceding comparison instruction, jump to <label> if <op1> > <op2>.
    Label must be defined exactly once.

    Examples:

    cmp   rax, 5
    jg    wasGreater
    
    jge <label>

    For signed data, based on preceding comparison instruction, jump to <label> if <op1> <op2>.
    Label must be defined exactly once.

    Examples:

    cmp   rax, 5
    jge    wasGreaterOrEqual
    
    jb <label>

    For unsigned data, based on preceding comparison instruction, jump to <label> if <op1> < <op2>.
    Label must be defined exactly once.

    Examples:

    cmp   rax, 5
    jb    wasLess
    
    jbe <label>

    For unsigned data, based on preceding comparison instruction, jump to <label> if <op1> <op2>.
    Label must be defined exactly once.

    Examples:

    cmp   rax, 5
    jbe    wasLessOrEqual
    
    ja <label>

    For unsigned data, based on preceding comparison instruction, jump to <label> if <op1> > <op2>.
    Label must be defined exactly once.

    Examples:

    cmp   rax, 5
    ja    wasGreater
    
    jae <label>

    For unsigned data, based on preceding comparison instruction, jump to <label> if <op1> <op2>.
    Label must be defined exactly once.

    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.
    Note, label must be defined exactly once.

    Examples:

    loop  startLoop
    loop  ifDone
    loop  sumLoop
    

    A more complete list of the instructions is located in Appendix B.


    7.7: Control Instructions is shared under a not declared license and was authored, remixed, and/or curated by LibreTexts.

    • Was this article helpful?