简体   繁体   English

FLD 浮点指令

[英]FLD floating-point instruction

According to http://cs.smith.edu/~thiebaut/ArtOfAssembly/CH14/CH14-4.html#HEADING4-5根据http://cs.smith.edu/~thiebaut/ArtOfAssembly/CH14/CH14-4.html#HEADING4-5

14.4.4.1 The FLD Instruction 14.4.4.1 FLD 指令
fld mem_32 fld mem_32
fld mem_64[bx] fld mem_64[bx]

My objective is store a constant 10 into my fPU stack.我的目标是将常量 10 存储到我的 fPU 堆栈中。 Why I cant do this?为什么我不能这样做?

__asm
{
  move bx, 0x0004;
  fld dword ptr[bx] or fld bx;


  //-------
  fld 0x004; //Since it is 32 bits?
  fild 0x004;     
}

At least three things can go wrong here.这里至少有三件事可能会出错。 One is the syntax of the assembler.一是汇编器的语法。 The second is instruction set architecture.二是指令集架构。 The third is the memory model (16 bit vs 32 bit, segmented vs flat).第三个是内存模型(16 位 vs 32 位,分段 vs 扁平)。 I suspect that the examples provided are targeted at 16-bit segmented architecture as the 8087 is from those ages, but c++ compilers mainly arrived after 386+ protected mode.我怀疑所提供的示例是针对 16 位分段架构的,因为 8087 来自那个时代,但是 c++ 编译器主要是在 386+ 保护模式之后出现的。

The 8087 FPU does not support instructions that move data between general purpose registers (GPR) and floating point stack. 8087 FPU 不支持在通用寄存器 (GPR) 和浮点堆栈之间移动数据的指令。 The rationale is that floating point registers use 32, 64 or 80 bits, while the GPRs are only 16 bit wide.基本原理是浮点寄存器使用 32、64 或 80 位,而 GPR 只有 16 位宽。 Instead on moves data indirectly from memory.取而代之的是从内存中间接移动数据。

The example fld myRealVar presupposes that a label (with a width) has been provided:示例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

Notice first that these examples assume that data belongs to a segment .data and that one has initialized the segment with首先请注意,这些示例假设数据属于一个段.data并且已经用

 mov  ax, segment data;  //
 mov  ds, ax

Only after that the memory location 0x0004 could possibly contain the constant 10. I strongly suspect that that model isn't available with your inline c++ system.只有在那之后,内存位置0x0004可能包含常量 10。我强烈怀疑该模型不适用于您的内联 C++ 系统。 Also here the assembler has to be smart enough to associate each label with the provided width and encode that in the instruction.同样在这里,汇编器必须足够聪明,才能将每个标签与提供的宽度相关联,并在指令中对其进行编码。

One way to load the integer into FPU is to use the stack:将整数加载到 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

In 32-bit architecture one can directly use esp to point the top of stack, which is probably the case with your c++ compiler:在 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

Some inline assemblers may be able to use local variables and automatically substitute the label with ebp/esp register and the correct offset:一些内联汇编器可能能够使用局部变量并自动用 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]
     }
 }

Note for clarity: BX is a 16 bit register indeed.为清楚起见,请注意:BX 确实是一个 16 位寄存器。 It still exists, but the FLD instruction doesn't support it.它仍然存在,但 FLD 指令不支持它。 The syntax for the 1st two lines should be:第一两行的语法应该是:

mov ebx, 4 mov ebx, 4

fld ebx fld ebx

When inlined in C/C++ the __asm styntax may be supported by the compiler.当在 C/C++ 中内联时,编译器可能支持 __asm 语法。 The answer above assumes a separate ASM file compiled with a separate assembler.上面的答案假设一个单独的 ASM 文件是用单独的汇编程序编译的。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM