根据 http://cs.smith.edu/~thiebaut/ArtOfAssembly/CH14/CH14-4.html#HEADING4-5
14.4.4.1 FLD指令我的目标是将一个常量10存储到我的fPU堆栈中。 为什么我不能这样做?
__asm
{
move bx, 0x0004;
fld dword ptr[bx] or fld bx;
//-------
fld 0x004; //Since it is 32 bits?
fild 0x004;
}
答案 0 :(得分:4)
这里至少有三件事可能出错。一个是汇编程序的语法。第二个是指令集架构。第三个是内存模型(16位vs 32位,分段vs平面)。我怀疑提供的示例是针对16位分段架构,因为8087来自那些年龄段,但c ++编译器主要是在386+保护模式之后到达的。
8087 FPU不支持在通用寄存器(GPR)和浮点堆栈之间移动数据的指令。基本原理是浮点寄存器使用32,64或80位,而GPR只有16位宽。而是间接从内存中移动数据。
示例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]
}
}
答案 1 :(得分:-1)
为清楚起见,请注意: BX确实是一个16位寄存器。它仍然存在,但是FLD指令不支持它。 前两行的语法应为:
mov ebx,4
fld ebx
在C / C ++中内联时,编译器可能支持__asm语法。 上面的答案假设使用单独的汇编器编译了单独的ASM文件。