В соответствии с
http://cs.smith.edu/~thiebaut/ArtOfAssembly/CH14/CH14-4.html#HEADING4-5
14.4.4.1 Инструкция FLD
поле mem_32
поле 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-битная или 32-битная, сегментированная и плоская). Я подозреваю, что представленные примеры нацелены на 16-битную сегментированную архитектуру, поскольку 8087 относится к тому же периоду, но компиляторы c ++ в основном поступили после 386+ защищенного режима.
FPU 8087 не поддерживает инструкции, которые перемещают данные между регистрами общего назначения (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]
}
}
Других решений пока нет …