首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >用数组的值从FPU堆栈加载错误的结果

用数组的值从FPU堆栈加载错误的结果
EN

Stack Overflow用户
提问于 2019-08-05 17:22:30
回答 1查看 252关注 0票数 1

我正在编写内联x86程序集代码,以便将用C语言定义的数组的内容复制到x87 FPU堆栈以执行进一步的操作。当我从FPU堆栈中检索它时,存储在FPU堆栈顶部的值是不同的。

我试着查看编译器生成的反汇编;参考了TurboPentium3.0手册;参考了8086年到奔腾汇编()教材,但找不到解决这个问题的方法。

我的代码是:

代码语言:javascript
复制
#include<stdio.h>

void main()
{
    float array[10] = { 1.13,1.98,1.67,1.19},sum;
asm{
    lea ax,[array]
    push ax
    fld dword ptr[bp-8]
    fstp sum
}
printf("%f", sum);
}

它编译时没有错误,但是当运行时我得到-786.997,而不是预期的结果1.67。

EN

回答 1

Stack Overflow用户

发布于 2019-08-05 19:31:16

在此代码中:

代码语言:javascript
复制
    lea ax,[array]
    push ax
    fld dword ptr[bp-8]
    fstp sum

您正在将array的地址加载到AX中,而不是该值。然后将AX中的array地址推到堆栈上。然后,您的FLD指令尝试从相对于BP的固定偏移量中读取数据。正如@Jester所指出的,您不应该依赖堆栈上的数据作为BP的特定偏移,因为它依赖于Turbo-C的代码生成器以及堆栈上的位置。

如果要读取数组的第三个元素,可以加载数组的地址,然后访问各个元素的地址。将array的地址加载到BX、SI或DI寄存器中,因为它们可以作为16位寻址模式中的基(AX不能)。

您的代码看起来可能是:

代码语言:javascript
复制
#include<stdio.h>

void main()
{
    float array[] = { 1.13,1.98,1.67,1.19 }, sum;
    asm{
        lea bx,[array]      /* Load address of array into BX */
        fld dword ptr[bx+8] /* Load the value at 3rd element. Each float is 4 bytes
                               in 16-bit Turbo-C thus [bx+8] is the third element */
        fstp [sum]          /* Store top of stack ST(0) to SUM and pop top of stack */
    }
    printf("%f", sum);
}

从最高数组元素到最低数组元素之和浮点数组的代码如下所示:

代码语言:javascript
复制
#include<stdio.h>

void main()
{
    float array[] = { 1.13,1.98,1.67,1.19 }, sum;
    const int array_size_b = sizeof (array);
                            /* Size of array in bytes */
    asm {
        lea bx,[array]      /* Load address of array into BX */
        mov si, [array_size_b]
                            /* SI = byte offset to element just past end of array */
        fldz                /* Push an initial SUM value (0.0) on the FPU stack */
    }
    sumloop:
    asm {
        fadd dword ptr[bx+si-4]
                            /* Add current float to SUM on top of FPU stack */
        sub si, 4           /* Set index to previous float in array */
        jnz sumloop         /* If not start of array go back and process next element */

        fstp [sum]          /* Retrieve SUM from top of FPU stack&store in variable sum */
    }
    printf("%f", sum);
}

按反向顺序处理元素简化了检查是否处理了整个数组的逻辑。从第一个元素到最后一个元素都可以这样做:

代码语言:javascript
复制
#include<stdio.h>

void main()
{
    float array[] = { 1.13,1.98,1.67,1.19 }, sum;
    const int array_size_b = sizeof (array);
    asm {
        lea bx,[array]       /* Load address of array into BX */
        xor si, si           /* SI = index into array = 0 = first element */
        mov cx, [array_size_b]
                             /* CX = byte offset of element just past end of array */
        fldz                 /* Push an initial SUM value (0.0) on the FPU stack */
    }
    sumloop:
    asm {
        fadd dword ptr[bx+si]/* Add the current float to SUM on top of FPU stack */
        add si, 4            /* Advance index to next float in array */
        cmp si, cx           /* Has the index reached the end of array? */
        jl sumloop           /* If not end of array go back and process next element */

        fstp [sum]           /* Retrieve SUM from top of FPU stack&store in variable sum */
    }
    printf("%f", sum);
}

观察

使用浮点单元( x87 FPU )的处理器上实际上有两种类型的堆栈。SS:SP所指向的调用堆栈和x87 FPU寄存器堆栈。如果将某些内容推到调用堆栈上,则FPU堆栈指令将弹出顶部元素,仅从FPU寄存器堆栈中弹出。如果您使用push ax在调用堆栈上推送一些东西,那么您应该考虑在内联程序集完成时重新平衡调用堆栈。您可以使用pop axadd sp, 2

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/57363338

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档