64位NASM汇编ALP计算统计量异常:方差为无穷大,GDB调试变量为0
Hey there, let's tackle your two core problems head-on: variance calculating as infinity and GDB consistently showing variables as 0. I'll break down common causes and actionable fixes based on the code snippet you shared.
First: Fix the GDB Variable Display Problem (This Will Unlock Real Debugging)
If GDB is showing your variables as 0, it's almost certainly a quirk of how GDB handles x87 floating-point registers and memory-stored floats—not that your values are actually zero. Here's how to see the real data:
- If you're using x87 instructions (like
fld,fstp) for calculations, view the floating-point register state directly with:
This will list all x87 stack registers and their actual values, so you can verify your mean and intermediate variance calculations.info float - If your floats are stored in memory (e.g., defined with
dq), use GDB's formatted inspection to avoid integer misinterpretation:print/double &variance_var # Replace variance_var with your actual variable name # Or use hex dump with float formatting x/fg &variance_var
Next: Diagnose the Infinite Variance Issue
Infinite variance in x87 assembly usually stems from logic errors, mismanaged floating-point registers, or type mismatches. Let's go through the most likely culprits:
1. Flawed Variance Calculation Logic
Variance relies on correctly summing (x_i - mean)^2 then dividing by the number of samples. Common mistakes here include:
- Uninitialized sum variable: If your square-difference accumulator (e.g.,
sum_sq) isn't set to0.0initially, it might hold a garbage value that leads to infinity. Always initialize floating-point variables in.dataexplicitly:sum_sq dq 0.0 ; Initialize square difference sum to 0.0 - Incorrect squaring or subtraction: Make sure you're using floating-point instructions for all steps. For example, to calculate
(x_i - mean)^2:fld qword [rsi] ; Load data point x_i fsub qword [mean] ; x_i - mean (floating-point subtraction) fmul st0, st0 ; Square the result (st0 * st0) fadd qword [sum_sq] ; Add to the accumulator fstp qword [sum_sq] ; Save updated sum back to memory - Dividing by an integer instead of a float: If your sample count
nis stored as an integer, you need to convert it to a double before dividing. Skipping this can lead to division by zero (or invalid float operations):; Convert integer n to double fild qword [n] ; Load integer n into x87 stack, convert to float fstp qword [n_float] ; Save as double-precision float ; Calculate variance: sum_sq / n_float fld qword [sum_sq] fdiv qword [n_float] fstp qword [variance]
2. Mismanaged X87 Floating-Point Registers
The x87 stack is easy to mess up—if you don't clean up registers after use, leftover values can corrupt calculations.
- Initialize the coprocessor first: Add
finitat the start of your calculation code to reset the x87 stack and state to a clean slate:finit ; Reset floating-point coprocessor to avoid garbage values - Balance stack operations: Every
fld(load) should have a correspondingfstp(store and pop) orffree(free register) to prevent stack overflow/underflow. Unbalanced stacks lead to unpredictable results, including infinity.
3. Your rw Macro Isn't For Formatted Output
Looking at your rw macro, it's a wrapper for the write syscall—but your msg1/msg2 use %lf format specifiers. The write syscall doesn't parse formatted strings; it just dumps raw bytes to stdout. This means you're seeing %lf as literal text, not the actual float value.
To properly print floating-point numbers, use printf (link against libc):
extern printf section .data msg1 db "Mean is: %lf", 10, 0 mean dq 3.0 section .text global main main: mov rdi, msg1 ; First argument: format string movq xmm0, [mean] ; Float argument goes in XMM0 (64-bit calling convention) mov rax, 1 ; Tell printf we're passing 1 float argument call printf ; Exit cleanly mov rax, 60 syscall
Note: In 64-bit Linux, floating-point arguments for libc functions are passed in XMM registers, not x87. If you're using x87 for calculations, transfer values to XMM registers with fstp qword [temp] followed by movq xmm0, [temp].
Quick Checklist to Debug
- Run
info floatin GDB to verify your mean and intermediate variance values are correct. - Ensure all floating-point variables are initialized to
0.0where needed. - Check that every x87
fldhas a matchingfstp/ffreeto keep the stack balanced. - Convert integer values (like sample count) to doubles before floating-point division.
- Replace raw
writecalls withprintfto see actual float values instead of format specifiers.
内容的提问来源于stack exchange,提问作者Aseem Kannal

