2013-05-12 36 views
-1

根据 http://cs.smith.edu/~thiebaut/ArtOfAssembly/CH14/CH14-4.html#HEADING4-5FLD浮点指令

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;  
} 
+1

你是什么“不能做”?你使用的是什么操作系统/编译器?地址4是什么,它实际上可以访问吗?大多数操作系统将阻止您使用地址4,因为它受“NULL访问检测”保护。 – 2013-05-12 06:08:10

回答

3

这里至少有三件事可能出错。一个是汇编程序的语法。第二个是指令集架构。第三个是内存模型(16位与32位,分段与平面)。我怀疑提供的例子是针对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.123456789
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] 
    } 
}