我正在编写内联x86程序集代码,以便将用C语言定义的数组的内容复制到x87 FPU堆栈以执行进一步的操作。当我从FPU堆栈中检索它时,存储在FPU堆栈顶部的值是不同的。
我试着查看编译器生成的反汇编;参考了TurboPentium3.0手册;参考了8086年到奔腾汇编()教材,但找不到解决这个问题的方法。
我的代码是:
#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。
发布于 2019-08-05 19:31:16
在此代码中:
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不能)。
您的代码看起来可能是:
#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);
}从最高数组元素到最低数组元素之和浮点数组的代码如下所示:
#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);
}按反向顺序处理元素简化了检查是否处理了整个数组的逻辑。从第一个元素到最后一个元素都可以这样做:
#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 ax或add sp, 2。
https://stackoverflow.com/questions/57363338
复制相似问题