Which instruction is used to convert an integer value to float and push it onto the FPU stack?

A good tutorial for the x87 FPU is beyond the scope of Stackoverflow but I can recommend the one on MASM forums. Another good source is the Intel Instruction Set Reference. In particular most functions starting with F are the x87 floating point unit (FPU) related instructions.

In general you can't just add a floating point value to an integer. They are two different representations. What you can do is convert the integer to a floating point value and then do floating point computations with it. In particular the instructions that start with FI are floating point operations that involve a conversion of an integer memory operand to floating point.

There are many ways to skin a cat, but if you review the FPU tutorial linked to above you may realize that one simplistic way is to do this:

sub esp, 8           ; Allocate space on stack to store integer
mov dword [esp], 2   ; Move the 32-bit integer value onto stack temporarily
fild dword [esp]     ; Load integer 2 from stack into top of FPU stack at st(0)
                     ;    Converting it to 2.0 in the process
mov dword [esp], __float32__(3.25)
                     ; Move 3.25 onto stack temporarily
fadd dword [esp]     ; Add 3.25 to st(0). Result in st(0). So st(0)=5.25
fstp qword [esp]     ; Store 64-bit double to stack for printf and pop FPU stack.

Rather than using global variables to store values in main memory temporarily I used the stack space we reserve as a temporary staging area to load/operate with the x87 FPU.

If you are on a CPU that supports the SSE2 instruction set (This includes any X86-64 processor in 32-bit mode) then you have other options. One is to use the SIMD instructions and registers to do 32-bit and 64-bit floating point operations. Using the instruction set reference you find some useful instructions like:

  • cvtsi2sd : Convert Dword Integer to Scalar Double-Precision FP Value
  • cvtss2sd : Convert Scalar Single-Precision FP Value to Scalar Double-Precision FP Value
  • addsd : Add Scalar Double-Precision Floating-Point Values
  • movsd : Move Scalar Double-Precision Floating-Point Value

A Scalar Single-Precision FP value is a 32-bit float. A Scalar Double-Precision is a 64-bit double.

sub esp, 8
mov dword [esp], 2      ; Load integer 2 (32-bit signed value) onto stack temporarily
cvtsi2sd xmm0, [esp]    ; Convert 2 on stack to 64-bit float and store in XMM0
mov dword [esp], __float32__(3.25)
                        ; Load 32-bit float value of 3.25 onto stack
cvtss2sd xmm1, [esp]    ; Load 32-bit single and convert it to 64-bit double. Store in XMM1
addsd xmm0, xmm1        ; Add 64-bit float in XMM0 and XMM1 store XMM0
movsd qword [esp], xmm0 ; Move 64-bit float back onto stack to be printed by printf

The trunc instructions, are used for converting floating points to integers. It's named truncate since it truncates the fractional part of the number when doing the conversion. There are signed and unsigned versions of this instruction.

There's another trunc instruction that truncates the fractional part of a floating point without converting it to and integer.

Try it

Syntax

;; push an f32 onto the stack
f32.const 10.5

;; convert from f32 to signed i32 rounding towards zero (.5 will be lost)
i32.trunc_f32_s

;; the top item on the stack will now be the value 10 of type f32

InstructionBinary opcode
i32.trunc_f32_s 0xa8
i32.trunc_f32_u 0xa9
i32.trunc_f64_s 0xaa
i32.trunc_f64_u 0xab
i64.trunc_f32_s 0xae
i64.trunc_f32_u 0xaf
i64.trunc_f64_s 0xb0
i64.trunc_f64_u 0xb1

  • Index
  • April 2022
OpcodeInstruction64-Bit ModeCompat/Leg ModeDescription
DF /0 FILD m16int Valid Valid Push m16int onto the FPU register stack.
DB /0 FILD m32int Valid Valid Push m32int onto the FPU register stack.
DF /5 FILD m64int Valid Valid Push m64int onto the FPU register stack.

Description ¶

Converts the signed-integer source operand into double extended-precision floating-point format and pushes the value onto the FPU register stack. The source operand can be a word, doubleword, or quadword integer. It is loaded without rounding errors. The sign of the source operand is preserved.

This instruction’s operation is the same in non-64-bit modes and 64-bit mode.

Operation ¶

TOP := TOP − 1;
ST(0) := ConvertToDoubleExtendedPrecisionFP(SRC);

FPU Flags Affected ¶

C1 Set to 1 if stack overflow occurred; set to 0 otherwise.
C0, C2, C3 Undefined.

Floating-Point Exceptions ¶

#IS Stack overflow occurred.

Protected Mode Exceptions ¶

#GP(0) If a memory operand effective address is outside the CS, DS, ES, FS, or GS segment limit.
If the DS, ES, FS, or GS register contains a NULL segment selector.
#SS(0) If a memory operand effective address is outside the SS segment limit.
#NM CR0.EM[bit 2] or CR0.TS[bit 3] = 1.
#PF(fault-code) If a page fault occurs.
#AC(0) If alignment checking is enabled and an unaligned memory reference is made while the current privilege level is 3.
#UD If the LOCK prefix is used.

Real-Address Mode Exceptions ¶

#GP If a memory operand effective address is outside the CS, DS, ES, FS, or GS segment limit.
#SS If a memory operand effective address is outside the SS segment limit.
#NM CR0.EM[bit 2] or CR0.TS[bit 3] = 1.
#UD If the LOCK prefix is used.

Virtual-8086 Mode Exceptions ¶

#GP(0) If a memory operand effective address is outside the CS, DS, ES, FS, or GS segment limit.
#SS(0) If a memory operand effective address is outside the SS segment limit.
#NM CR0.EM[bit 2] or CR0.TS[bit 3] = 1.
#PF(fault-code) If a page fault occurs.
#AC(0) If alignment checking is enabled and an unaligned memory reference is made.
#UD If the LOCK prefix is used.

Compatibility Mode Exceptions ¶

Same exceptions as in protected mode.

64-Bit Mode Exceptions ¶

#SS(0) If a memory address referencing the SS segment is in a non-canonical form.
#GP(0) If the memory address is in a non-canonical form.
#NM CR0.EM[bit 2] or CR0.TS[bit 3] = 1.
#MF If there is a pending x87 FPU exception.
#PF(fault-code) If a page fault occurs.
#AC(0) If alignment checking is enabled and an unaligned memory reference is made while the current privilege level is 3.
#UD If the LOCK prefix is used.

Which instruction is used to initialize the FPU?

Which instruction is used to initialize the FPU? The IA-32 FPU FLD instruction can only load in REAL10 floats, not REAL4 or REAL8. The IA-32 FPU is directly connected to the ALU via internal bus.

What instruction would I use to save the current value of the flags register?

What instruction would I use to save the current value of the flags register? Mechanically speaking, the CALL instruction pushes its return address on the stack and copies the called procedure's address into the instruction pointer.