Skip to main content
Engineering LibreTexts

18.6: Floating-Point Control Instructions

  • Page ID
    19979
  • \( \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}}\)

    The control instructions refer to programming constructs such as IF statements and looping. The integer comparison instruction, cmp, as described in Chapter 7 will not work for floating-point values.

    The floating-point comparison instructions compare two floating-point values. Like the integer comparisons, the result of the comparison is stored in the rFlag register and neither operand is changed. Immediately after the comparison, the rFlag register is accessed to determine the results by using a conditional jump instruction. While all floating-point comparisons are signed, an unsigned conditional jump is used (ja/jae/jb/jbe). Program labels (i.e., a target of a conditional jump) are the same.

    There are two forms of the floating-point comparison, ordered and unordered. The ordered floating-point comparisons can cause a number of exceptions. The unordered floating-point comparisons can only cause an exception for a S-NaN (signaling not a number), more generically referred to as a NaN (not a number) as described in Chapter 3, Data Representation.

    The GNU C/C++ compiler favors the unordered floating-point compare instruction. Since they are similar, this text will focus only on the unordered version.

    Floating-Point Comparison

    The general form of the floating-point comparison instructions are as follows:

         ucomiss    <RXsrc>, <src>
         ucomisd    <RXsrc>, <src>
    

    Where <RXsrc> and <src> are compared as floating-point values and must be the same size. The results of the comparison are placed in the rFlag register. Neither operand is changed. The <RXsrc> operand must be one of the xmm registers. The <src> register can be a xmm register or a memory location, but may not be an immediate value. One of the unsigned conditional jump instructions can be used to read the rFlag register.

    The conditional control instructions include the jump equal (je) and jump not equal (jne). 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:

        je     <label>         ; if <op1> == <op2> 
        jne    <label>         ; 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 floating-point variables:

         if (fltNum > fltMax)
               fltMax = fltNum;
    

    And, given the following data declarations:

        fltNum     dq     7.5 
        fltMax     dq     5.25
    

    Then, assuming that the values are updating appropriately within the program (not shown), the following instructions could be used:

       movsd        xmm1, qword [fltNum]
       ucomisd      xmm1, qword [fltMax]        ; if fltNum <= fltMax
       jbe          notNewFltMax                ;    skip set new max
       movsd        qword [fltMax], xmm1
    notNewFltMax:
    

    As with integer comparisons, the floating-point 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 to update the fltMax should 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.0) {
               ans = x / y;           
               errFlg = FALSE;
         } else {           
               errFlg = TRUE;
         }
    

    This basic compare and conditional jump does not provide and 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 
        fltZero      dq      0.0 
        x            dq      10.1 
        y            dq      3.7 
        ans          dq      0.0 
        errFlg       db      FALSE
    

    The following code could be used to implement the above IF-ELSE statement.

        movsd       xmm1, qword [x] 
        ucomisd     xmm1, qword [fltZero]         ; if statement
        je          doElse
        divsd       xmm1, qword [y] 
        movsd       dword [ans], eax
        mov         byte [errFlg], FALSE 
        jmp         skpElse
    
    doElse:
        mov         byte [errFlg], TRUE
    skpElse:
    

    Floating-point comparisons can be very tricky due to the inexact nature of the floating- point representations and rounding errors. For example, the value 0.1 added 10 times should be 1.0. However, implementing a program to perform this summation and checking the result, will show that;

    \[\sum_{i = 1}^{10} 0.1 \ne 1.0 \nonumber\]

    which can be very confusing for inexperienced programmers.

    For more information regarding the details of floating-point, refer to the popular article What Every Computer Scientist Should Know About Floating-Point Arithmetic(See: http://docs.oracle.com/cd/E19957-01/..._goldberg.html).

    The floating-point comparison instructions are summarized as follows:

    Instruction

    Explanation

    ucomiss   <RXsrc>, <src>
    

    Compare two 32-bit floating-point operands, (<RXsrc> + <src>). Results are placed in the rFlag register. Neither operand is changed.
    Note 1, <RXsrc> operands must be a floating- point register.
    Note 2, source operand may be a floating-point register or memory, but not be an immediate.

    Examples:

    ucomiss   xmm0, xmm3
    ucomiss   xmm5, dword [fSVar]
    
    ucomisd   <RXsrc>, <src>
    

    Compare two 64-bit floating-point operands, (<RXsrc> + <src>). Results are placed in the rFlag register. Neither operand is changed.
    Note 1, <RXsrc> operands must be a floating- point register.
    Note 2, source operand may be a floating-point register or memory, but not be an immediate.

    Examples:

    ucomisd   xmm0, xmm3
    ucomisd   xmm5, qword [fSVar]
    

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


    This page titled 18.6: Floating-Point Control Instructions is shared under a CC BY-NC-SA license and was authored, remixed, and/or curated by Ed Jorgensen.

    • Was this article helpful?