Grundlagen der x87-FPU-Programmierung
Lernen Sie, wie Sie die x87 Floating-Point Unit (FPU) für hochpräzise Gleitkommaarithmetik in Assembly verwenden.
Grundlagen der x87-FPU-Programmierung ist eine kostenlose Assembly Language & x86 Low-Level Systems Programming-Lektion auf CoddyKit. Dies ist Lektion 1 von 4. Du kannst die komplette Lektion unten kostenlos lesen – dann übst du sie direkt im Browser mit einem integrierten Code-Editor und einem KI-Tutor rund um die Uhr. Sie ist Teil des Assembly Language & x86 Low-Level Systems Programming-Lernpfads, und dein Fortschritt wird über Web und CoddyKit-App synchronisiert. Der Assembly Language & x86 Low-Level Systems Programming-Kurs umfasst insgesamt 4 Lektionen.
Teile dieser Lektion wurden noch nicht übersetzt und werden auf Englisch angezeigt.
Meet the x87 FPU
The x87 Floating-Point Unit (FPU) is a specialized part of the CPU designed to handle mathematical operations on real numbers, also known as floating-point numbers.
Unlike integer arithmetic, floating-point math requires different internal representations and calculations, which the FPU excels at with high precision.
The FPU Register Stack
The x87 FPU uses a unique register stack, not general-purpose registers. This stack consists of eight 80-bit registers, denoted as ST(0) through ST(7).
ST(0)is always the top of the stack.- Operations push new values onto the stack or pop values from it, shifting existing values.
- It behaves like a Last-In, First-Out (LIFO) stack.
Loading Data with FLD
To work with floating-point numbers, you first need to load them onto the FPU stack. The FLD instruction pushes a floating-point value from memory onto the top of the FPU stack, making it ST(0).
In assembly, we often define floating-point constants in the data section. Common types are single-precision (32-bit, DD) and double-precision (64-bit, DQ).
Try loading a value onto the stack:
section .data
float_val dq 3.1415926535
section .text
global _start
_start:
finit ; Initialize FPU
fld qword [float_val] ; Load float_val onto FPU stack (ST(0))
; At this point, ST(0) contains 3.1415926535
; We just exit as printing floats is complex in basic assembly.
mov rax, 60 ; syscall number for exit
xor rdi, rdi ; exit code 0
syscallStoring FPU Results
After calculations, you'll want to store the result from the FPU stack back into memory. The FST and FSTP instructions are used for this.
FST: Copies the value fromST(0)to a memory location or another FPU register, leavingST(0)unchanged.FSTP: Copies the value fromST(0)to memory/register, then pops it from the stack, decreasing the stack pointer. The previousST(1)becomesST(0).
Let's store a value:
section .data
float_val dq 123.45
result_val dq 0.0 ; Will store result here
section .text
global _start
_start:
finit ; Initialize FPU
fld qword [float_val] ; ST(0) = 123.45
fstp qword [result_val] ; Store ST(0) to result_val, then pop.
; FPU stack is now empty.
; result_val now holds 123.45 in memory.
mov rax, 60 ; syscall number for exit
xor rdi, rdi ; exit code 0
syscallFPU Arithmetic Operations
The FPU provides instructions for common arithmetic operations. These typically operate on ST(0) and another operand (either another stack register or a memory operand).
FADD: Add (e.g.,FADD ST(1), ST(0)addsST(0)toST(1)).FMUL: MultiplyFSUB: SubtractFDIV: Divide
Using FADDP ST(1), ST(0) adds ST(0) to ST(1), stores in ST(1), and pops ST(0). This leaves the sum on top of the stack.
Here's an addition example:
section .data
val1 dq 10.5
val2 dq 2.0
sum_result dq 0.0
section .text
global _start
_start:
finit ; Initialize FPU
fld qword [val1] ; ST(0) = 10.5
fld qword [val2] ; ST(0) = 2.0, ST(1) = 10.5
faddp st(1), st(0) ; ST(1) = ST(1) + ST(0) (10.5 + 2.0 = 12.5).
; Pop ST(0). Now ST(0) = 12.5.
fstp qword [sum_result] ; Store 12.5 to sum_result and pop.
mov rax, 60 ; syscall number for exit
xor rdi, rdi ; exit code 0
syscallFPU Built-in Constants
The FPU can load commonly used constants directly onto its stack, saving you from defining them in memory. This improves efficiency and precision.
FLD1: Pushes 1.0 onto the stack.FLDZ: Pushes 0.0 onto the stack.FLDPI: Pushes the value of Pi (π) onto the stack.
Let's load Pi:
section .data
pi_val dq 0.0 ; To store PI
section .text
global _start
_start:
finit ; Initialize FPU
fldpi ; ST(0) = PI (approx 3.14159...)
fstp qword [pi_val] ; Store PI to pi_val and pop.
mov rax, 60 ; syscall number for exit
xor rdi, rdi ; exit code 0
syscallConverting Integers & Floats
Sometimes you need to convert between integer and floating-point types. The FPU provides instructions for this:
FILD(Float Integer Load): Loads a signed integer from memory, converts it to a floating-point format, and pushes it onto the FPU stack.FISTP(Float Integer Store and Pop): StoresST(0)as an integer to memory and then pops it from the stack. The value is truncated towards zero during conversion.
Let's convert an integer to a float, add, then convert back:
section .data
int_val dd 5
float_add dq 2.5
int_result dd 0
section .text
global _start
_start:
finit ; Initialize FPU
fild dword [int_val] ; ST(0) = 5.0 (from 5)
fld qword [float_add] ; ST(0) = 2.5, ST(1) = 5.0
faddp st(1), st(0) ; ST(1) = 5.0 + 2.5 = 7.5. Pop ST(0).
; Now ST(0) = 7.5.
fistp dword [int_result] ; Store 7.5 as integer (7) to int_result and pop.
mov rax, 60 ; syscall number for exit
xor rdi, rdi ; exit code 0
syscallComparing Floating-Point Values
Comparing floating-point numbers requires special FPU instructions. You can't directly use integer comparison instructions like CMP.
FCOM: ComparesST(0)with an operand (another FPU register or memory) and sets FPU status flags.FCOMP: Same asFCOM, but popsST(0)after comparison.
To use these flags for conditional jumps (like JE, JB), you must transfer them from the FPU status word to the CPU's EFLAGS register:
FSTSW AX: Stores the FPU Status Word into theAXregister.SAHF: Transfers theAHregister (which now contains the relevant FPU flags) into the CPU'sEFLAGSregister, specifically theZF,PF, andCFflags.
Putting it Together: (A + B) * C
Let's combine what we've learned to perform a simple calculation: (A + B) * C. We'll load three values, add two, multiply by the third, and store the final integer result.
This example demonstrates stack manipulation and arithmetic operations.
section .data
val_A dq 3.0
val_B dq 1.5
val_C dq 2.0
final_int_result dd 0
section .text
global _start
_start:
finit ; Initialize FPU
fld qword [val_A] ; ST(0) = 3.0
fld qword [val_B] ; ST(0) = 1.5, ST(1) = 3.0
faddp st(1), st(0) ; Add ST(0) (1.5) to ST(1) (3.0), store in ST(1).
; Pop ST(0). Now ST(0) = 4.5 (sum of A+B)
fld qword [val_C] ; ST(0) = 2.0, ST(1) = 4.5 (A+B)
fmulp st(1), st(0) ; Multiply ST(0) (2.0) by ST(1) (4.5), store in ST(1).
; Pop ST(0). Now ST(0) = 9.0 ((A+B)*C)
fistp dword [final_int_result] ; Store 9.0 as integer (9) to final_int_result and pop.
mov rax, 60 ; syscall number for exit
xor rdi, rdi ; exit code 0
syscallFPU Stack Challenge
Consider the following x87 FPU assembly code snippet. What will be the value of ST(0) after its execution?
section .data
val_X dq 10.0
val_Y dq 3.0
section .text
finit
fld qword [val_X] ; ST(0) = 10.0
fld qword [val_Y] ; ST(0) = 3.0, ST(1) = 10.0
faddp st(1), st(0) ; ST(0) = 13.0
fld1 ; ST(0) = 1.0, ST(1) = 13.0
fsub ; ST(0) = ST(0) - ST(1) (1.0 - 13.0 = -12.0)x87 FPU Summary
You've taken your first steps into x87 FPU programming! We covered:
- The FPU's 8-register stack (
ST(0)toST(7)). - Loading values with
FLDand storing withFST/FSTP. - Basic arithmetic:
FADD,FSUB,FMUL,FDIV. - Using built-in constants like
FLD1,FLDZ,FLDPI. - Converting between integers and floats with
FILDandFISTP. - How to prepare FPU comparison results for conditional jumps.
The x87 FPU is powerful for precise calculations, though modern systems often use SIMD extensions like SSE/AVX for speed, which you'll explore next!
Häufig gestellte Fragen
Ist die Lektion „Grundlagen der x87-FPU-Programmierung“ kostenlos?
Ja — der vollständige Text von „Grundlagen der x87-FPU-Programmierung“ ist hier im Web kostenlos zu lesen. Um sie interaktiv zu üben (integrierter Code-Editor und 24/7 KI-Tutor) und den Rest des Assembly Language & x86 Low-Level Systems Programming-Kurses freizuschalten, upgrade auf CoddyKit PRO. Der Assembly Language & x86 Low-Level Systems Programming-Kurs umfasst insgesamt 4 Lektionen.
Was lerne ich in „Grundlagen der x87-FPU-Programmierung“?
Lernen Sie, wie Sie die x87 Floating-Point Unit (FPU) für hochpräzise Gleitkommaarithmetik in Assembly verwenden. Du übst Assembly Language & x86 Low-Level Systems Programming mit praktischem Code, den du direkt im Browser ausführst, und ein 24/7 KI-Tutor beantwortet deine Fragen während du die Lektion bearbeitest.
Brauche ich Erfahrung, um Assembly Language & x86 Low-Level Systems Programming zu starten?
Keine Vorkenntnisse erforderlich. Assembly Language & x86 Low-Level Systems Programming auf CoddyKit ist für Anfänger bis fortgeschrittene Lernende strukturiert, sodass du hier starten oder von Anfang an beginnen und in deinem eigenen Tempo voranschreiten kannst. Dies ist Lektion 1 von 4.
Wie lange dauert die Lektion „Grundlagen der x87-FPU-Programmierung“?
Die meisten CoddyKit-Lektionen dauern etwa 5–10 Minuten. Jede ist kompakt und interaktiv, sodass du stetig Fortschritte machst und genau dort weitermachst, wo du aufgehört hast – im Web und in der App.
Kann ich in dieser Assembly Language & x86 Low-Level Systems Programming-Lektion Code schreiben und ausführen?
Ja. Jede Assembly Language & x86 Low-Level Systems Programming-Lektion enthält einen integrierten Code-Editor, sodass du echten Code direkt in deinem Browser schreibst und ausführst und sofort KI-Feedback erhältst — ohne lokale Einrichtung erforderlich.
Alle Lektionen in diesem Kurs
- Grundlagen der x87-FPU-Programmierung
- Einführung in SSE/AVX-Instruktionssätze
- Code mit SIMD vektorisieren
- Gleitkommagenauigkeit, Rundung und Ausnahmen