Search code examples
assemblymasmmasm32x87

Compare float sum


I'm working on a MASM32 project that performs arithmetic operations. We have to use the coprocessor (8087 instruction set) to use the floating point unit. So, supose my floating point limit is 100.0 then every number must be less than the limit. I'm trying to sum two numbers and then compare the result but it doesn't work.

.386
.model flat, stdcall
option casemap :none
include \masm32\include\windows.inc
include \masm32\include\kernel32.inc
include \masm32\include\user32.inc
includelib \masm32\lib\kernel32.lib
includelib \masm32\lib\user32.lib
include c:\masm32\include\masm32rt.inc
.data
    ;Variables de comparación.
    FP_max DD 100
    ;Variables volcadas de la tabla de símbolos.
    _a DD 25
    _b DD 80.0
.code
    start:
         fild _a
         fild _b
         fadd
         fcom FP_max       ;compare ST(0) with the value of the real8_var variable
         fstsw ax          ;copy the Status Word containing the result to AX
         sahf              ;transfer the condition codes to the CPU's flag register
         ja overflow       ;when all flags are 0

        jmp end_program

        overflow:
            print "ERROR: overflow.", 13, 10, 0
            jmp end_program
        end_program:
            invoke ExitProcess, 0
    end start

My question is: what i'm doing wrong? How can it fix it? Thanks!


Solution

  • fild is an integer->FP load. fld is a float load. (Your assembler magically infers that you want a 32-bit load based by looking at the first directive after the label. The same instruction can load 64-bit integer or FP.)

    dd chooses integer or float encoding for the number based on whether there's a decimal point or not in the expression. (MASM probably has other ways to force FP interpretation, like REAL4. (Float data example using Masm)


    You use fild _b, but _b holds a 32-bit binary floating point value. Treating that bit-pattern as a 32-bit integer is probably not what you meant to do.

    Use _b DD 80 instead of _b DD 80.0, or use fld _b instead of fild _b.

    You have the reverse problem with FP_max DD 100, because you load it from memory with fcom. Make it REAL4.

    (Or use ficom, but note that there's not ficomi instruction to compare with an integer and set flags directly. There's fcomi (which you should use) that compares floats, and there's ficom which is like fild + fcomp but without needing an extra FP register. Same idea as fiadd).

    You should probably be using faddp and fcomip to also pop the x87 stack, so you don't leave it unbalanced.

    See some of the x87 links in the tag wiki.