加载常量的FLD浮点指令
FLD floating-point instruction to load a constant
根据The Art of Assembly CH14(链接已死,在archive.org上找不到)
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
fild word ptr [bp]
pop ax // clean the stack and restore bp
pop bp
.. or ..
mov bx, 10
push bx
mov bx, sp
fild 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指令不支持它。前两行的语法应该是:
盛名ebx
当在C/c++中内联时,编译器可能支持__asm styntax。上面的答案假设有一个单独的ASM文件,由一个单独的汇编器编译。
相关文章:
- 使用C++库在Android项目中修改gradle中的cmake参数,用于插入指令的测试
- 无法编译 rtmidi 测试 cmidiin.cpp 文件, 非法指令
- C++:对不存在的命名空间使用命名空间指令
- 函数名是c中该函数的第一条指令的地址吗
- 错误:无效的预处理指令 #i 的意思是 #if?
- 组装指令中乘法的下部和上部是什么
- OpenMP 与有序和关键指令并行
- C++中的移动分配出现问题.非法指令: 4.
- 嵌套命名空间的"using"指令,但需要命名内部命名空间
- C++CMake编译指令与
- 使用宏扩展的泛型:为什么指令缓存使用不当?
- 如何在 c++ 中确定一条指令(以字节为单位)在哪里结束,另一条指令从哪里开始?
- AVX 指令中寄存器和指针之间的客观差异
- while 循环 c++ 中的非法指令
- 如何在编译时定义C++预处理器指令的值?
- 存储指令是否会阻止缓存未命中的后续指令?
- 保证编译器指令在C++中重新排序
- VS2008中的AVX-512指令库
- 令人困惑的定义指令在C ++项目中
- 加载常量的FLD浮点指令