FLD浮点指令

时间:2013-05-12 03:32:32

标签: c++ assembly fpu

根据 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;     
}

2 个答案:

答案 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文件。