2013-05-12 35 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] 
    } 
}