这里至少有三件事可能出错。一个是汇编程序的语法。第二个是指令集架构。第三个是内存模型(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]
}
}
你是什么“不能做”?你使用的是什么操作系统/编译器?地址4是什么,它实际上可以访问吗?大多数操作系统将阻止您使用地址4,因为它受“NULL访问检测”保护。 – 2013-05-12 06:08:10