根据
http://cs.smith.edu/~thiebaut/ArtOfAssembly/CH14/CH14-4.html#HEADING4-5
14.4.4.1 FLD指令
fld mem_32
fld mem_64 [bx]
我的目标是将常数10存储到我的fPU堆栈中。
为什么我不能这样做?
__asm
{
move bx, 0x0004;
fld dword ptr[bx] or fld bx;
//-------
fld 0x004; //Since it is 32 bits?
fild 0x004;
}
最佳答案
至少有三件事可能会出错。一种是汇编器的语法。第二是指令集架构。第三个是内存模型(16位vs 32位,分段vs平面)。我怀疑所提供的示例针对的是16位分段体系结构,因为8087是从那个时代开始的,但是c ++编译器主要是在386+保护模式之后出现的。
8087 FPU不支持在通用寄存器(GPR)和浮点堆栈之间移动数据的指令。理由是浮点寄存器使用32位,64位或80位,而GPR仅16位宽。相反,on从存储器间接移动数据。
示例fld myRealVar
假定已提供标签(具有宽度):
.data
myRealVar: .real8 1.113134241241
myFloat: .real4 1.1131313
myBigVar: .real10 1.1234567890123456
myInt: .word 10
myInt2: .word 0
myBytes: .byte 10 dup (0) ;// initializes 10 bytes of memory with zeros
.text
fld myRealVar; // accesses 8 bytes of memory
fild myInt; // access the memory as 16 bits
fild myBytes; // ## ERROR ## can't load 8-bits of data
fild dword ptr myBytes; // Should work, as the proper width is provided
首先请注意,这些示例假定数据属于段
.data
,并且已使用初始化了该段。 mov ax, segment data; //
mov ds, ax
仅在此之后,内存位置
0x0004
可能包含常数10。我强烈怀疑该模型在嵌入式c ++系统中不可用。同样在这里,汇编器必须足够聪明,才能将每个标签与提供的宽度相关联并在指令中进行编码。将整数加载到FPU中的一种方法是使用堆栈:
push bp // save bp
mov ax, 10
push ax
mov bp, sp // use bp to point to stack
fld word ptr [bp]
pop ax // clean the stack and restore bp
pop bp
.. or ..
mov bx, 10
push bx
mov bx, sp
fld word ptr ss:[bx] // notice the segment override prefix ss
pop ax // clean the constant 10
在32位体系结构中,可以直接使用
esp
指向栈顶,这可能是c ++编译器的情况: sub esp, 4
mov dword ptr [esp], 10 // store the integer 10 into stack
fild dword ptr [esp] // access the memory
add esp, 4 // undo the "push" operation
一些内联汇编器可能能够使用局部变量,并自动将标签替换为ebp / esp寄存器和正确的偏移量:
int f1 = 10;
void myfunc(float f2) {
double f = 10.0;
__asm {
fild f1 // encoded as fild dword ptr [xxx]
fld f // encoded as fld qword ptr [esp + xxx]
fld f2 // encoded as fld dword ptr [esp + xxx]
}
}