簡體   English   中英

FLD 浮點指令

[英]FLD floating-point instruction

根據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 位寬。 取而代之的是從內存中間接移動數據。

示例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]
     }
 }

為清楚起見,請注意:BX 確實是一個 16 位寄存器。 它仍然存在,但 FLD 指令不支持它。 第一兩行的語法應該是:

mov ebx, 4

fld ebx

當在 C/C++ 中內聯時,編譯器可能支持 __asm 語法。 上面的答案假設一個單獨的 ASM 文件是用單獨的匯編程序編譯的。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM