You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

数组double元素无法加载至FP寄存器?汇编函数结果异常排查

点积函数汇编实现的问题排查与修复

问题描述

实现了C版本的点积函数,同时用x86 FPU汇编编写了同功能函数,但汇编版本始终返回0,调试时寄存器中显示随机数而非预期数组值,需要排查原因并修复,使汇编函数结果与C版本一致。

代码实现

C++点积函数

double fun_w22(double* xx, double* z, int N) {
    double result= 0.0;

    for (int i = 0; i < N; i++) {
        result+= xx[i] * z[i];
    }

    return result;
}

有问题的汇编实现

double fun_w22_asm(double* xx, double* z, int N) {
    double result= 0.0;
    __asm {
        mov ecx, N
        mov esi, xx
        mov edi, z 
        fld [esi]
        fld [edi]
        fmul [esi]  
        dec ecx 
    petla:
        add esi, 8
        add edi, 8
        fld[esi]
        fmul[edi]
        fadd
        dec ecx
    jnz petla
        fstp result
    }

    return result;
}

主函数调用

int main() {

    int N=3;
    
    double xx[] = { 1.0, 2.0, 3.0 }; // Sample array x
    double z[] = { 4.0, 5.0, 6.0 }; // Sample array z

    // Call the function to calculate the result
    double result = fun_w22(xx, z, N);
    double result1 = fun_w22_asm(xx, z, N);
    // Display the result
    std::cout << "Result: " << result << std::endl;
    std::cout << "Result ASM: " << result1 << std::endl;

    return 0;
}

问题原因

  1. FPU栈操作逻辑错误:初始步骤错误地压入两个数组元素,且后续未清理冗余的栈元素,导致FPU栈不平衡,最终计算结果被异常覆盖或程序状态混乱。
  2. 累加器初始化缺失:未将累加器初始化为0,反而引入了额外的未参与计算的数值留在栈中,干扰最终结果。
  3. 乘法与累加逻辑混乱:第一次乘法操作的操作数匹配错误,后续fadd操作未正确维护累加器的栈结构,导致计算过程中数值叠加错误。

修复后的汇编实现

double fun_w22_asm(double* xx, double* z, int N) {
    double result = 0.0;
    __asm {
        mov ecx, N
        mov esi, xx
        mov edi, z
        fldz                ; 初始化FPU栈顶为0.0,作为累加器
        test ecx, ecx       ; 检查N是否为0,处理边界情况
        jz end_loop         ; N=0时直接跳至结束

    petla:
        fld [esi]           ; 加载当前xx数组元素到FPU栈顶
        fmul [edi]          ; 栈顶元素 = xx[i] * z[i]
        faddp st(1), st(0)  ; 累加器(ST1) += 乘积(ST0),弹出栈顶,保持栈平衡
        add esi, 8          ; 指针移动到下一个double元素(占8字节)
        add edi, 8
        dec ecx
        jnz petla           ; 计数器不为0则继续循环

    end_loop:
        fstp result         ; 将累加结果存入result,同时弹出栈顶,平衡FPU栈
    }
    return result;
}

修复说明

  • 用fldz直接初始化累加器为0.0,确保从正确的初始值开始计算。
  • 统一通过循环处理所有元素,避免初始步骤的冗余错误操作,逻辑更简洁。
  • 使用faddp st(1), st(0)明确完成乘积与累加器的叠加,并维护FPU栈的平衡,避免栈溢出或数值残留。
  • 增加边界判断,处理N=0的情况,避免无效循环。
  • 确保指针每次移动8字节(对应double类型的长度),计数器递减逻辑正确。

修复后,汇编函数计算结果将与C++版本一致,对于测试用例返回32.0。

内容的提问来源于stack exchange,提问作者Biskopt

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.12 03:29:52