x87 FPU 프로그래밍 기초
어셈블리 언어에서 x87 부동 소수점 장치(FPU)를 사용하여 고정밀 부동 소수점 연산을 수행하는 방법을 학습합니다.
x87 FPU 프로그래밍 기초은(는) CoddyKit의 무료 Assembly Language & x86 Low-Level Systems Programming 강의입니다. 이것은 4개 중 1번째 강의입니다. 아래에서 전체 강의를 무료로 읽을 수 있으며, 내장 코드 에디터와 24/7 AI 튜터와 함께 브라우저에서 직접 실습할 수 있습니다. 이 강의는 Assembly Language & x86 Low-Level Systems Programming 학습 경로의 일부이며, 진행 상황이 웹과 CoddyKit 앱에 동기화됩니다. Assembly Language & x86 Low-Level Systems Programming 강의에는 총 4개의 강의가 포함되어 있습니다.
이 강의의 일부는 아직 번역되지 않았으며 영어로 표시됩니다.
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!
자주 묻는 질문
“x87 FPU 프로그래밍 기초” 강의는 무료인가요?
네 — “x87 FPU 프로그래밍 기초” 전체 내용을 이 웹사이트에서 무료로 읽을 수 있습니다. 인터랙티브하게 실습하려면(내장 코드 에디터와 24/7 AI 튜터), CoddyKit PRO로 업그레이드하면 Assembly Language & x86 Low-Level Systems Programming 강의 전체를 잠금 해제할 수 있습니다. Assembly Language & x86 Low-Level Systems Programming 강의에는 총 4개의 강의가 포함되어 있습니다.
“x87 FPU 프로그래밍 기초”에서 뭘 배우나요?
어셈블리 언어에서 x87 부동 소수점 장치(FPU)를 사용하여 고정밀 부동 소수점 연산을 수행하는 방법을 학습합니다. 브라우저에서 직접 실행하는 실습 코드로 Assembly Language & x86 Low-Level Systems Programming을(를) 배우며, 24/7 AI 튜터가 강의를 진행하면서 질문에 답변해줍니다.
Assembly Language & x86 Low-Level Systems Programming을(를) 시작하는 데 경험이 필요한가요?
사전 경험은 필요하지 않습니다. CoddyKit의 Assembly Language & x86 Low-Level Systems Programming은(는) 초급자부터 고급 학습자까지를 위해 구성되어 있으므로, 여기서 시작하거나 처음부터 시작할 수 있으며 자신의 속도대로 진행할 수 있습니다. 이것은 4개 중 1번째 강의입니다.
“x87 FPU 프로그래밍 기초” 강의는 얼마나 걸리나요?
대부분의 CoddyKit 강의는 약 5~10분이 소요됩니다. 각 강의는 간결하고 인터랙티브하여 꾸준한 진행이 가능하며, 웹과 앱에서 중단한 부분부터 바로 시작할 수 있습니다.
이 Assembly Language & x86 Low-Level Systems Programming 강의에서 코드를 작성하고 실행할 수 있나요?
네. 모든 Assembly Language & x86 Low-Level Systems Programming 강의에는 내장 코드 에디터가 포함되어 있으므로, 브라우저에서 바로 실제 코드를 작성하고 실행한 후 즉시 AI 피드백을 받을 수 있습니다 — 로컬 설정이 필요 없습니다.
이 강의의 모든 강의
- x87 FPU 프로그래밍 기초
- SSE/AVX 명령어 집합 소개
- SIMD를 사용한 코드 벡터화
- 부동소수점 정밀도, 반올림 및 예외