【发布时间】:2016-06-12 14:06:16
【问题描述】:
如何将存储在扩展寄存器(eax)中的值加载到浮点堆栈的st0中?
fld dword [eax]
当我使用上述指令时,我没有得到期望的传输变化,可能是因为括号符号与内存地址而不是内容有关。 不过,我不确定。
【问题讨论】:
-
EAX 是整数还是已经包含浮点值?
如何将存储在扩展寄存器(eax)中的值加载到浮点堆栈的st0中?
fld dword [eax]
当我使用上述指令时,我没有得到期望的传输变化,可能是因为括号符号与内存地址而不是内容有关。 不过,我不确定。
【问题讨论】:
您尝试使用此指令加载 EAX 不会像您认为的那样:
fld dword [eax]
这会从 EAX 指向的内存位置加载 32 位浮点值(这是indirect addressing)。我相信你想用 EAX 的值加载 ST(0)。
如果你必须使用 x87 FPU 指令而不是像 SSE 这样的指令,那么我建议暂时将值存储在 EAX 中堆栈而不是像@quasar66 建议的固定内存位置。把它放到栈上也可以让你的代码变成re-entrant。
如果代码在已经为临时对象分配空间的函数中,只需增加堆栈分配以允许将另一个 32 位值存储到其中并将 EAX 移动到该堆栈位置,然后使用fld 从那里加载。
最终,32 位代码可能被编写为具有类似的效果:
push EAX ; Store EAX to top of stack
fld dword [esp] ; Load 32-bit DWORD value at top of stack to ST(0)
POP EAX ; Restore stack, alternatively could have used add esp, 4
; do other floating point work here
在遵循 System V 64 位 ABI(不适用于 64 位 Windows)的 64 位操作系统上,您可以将数据直接移动到堆栈的red zone,而不必担心它会被破坏。这样的 64 位代码可能看起来像这样:
mov [rsp-4], eax ; Temporarily place EAX in the stack's red zone beneath current RSP
fld dword[rsp-4] ; Load it into ST0
; do other stuff here
; No need for stack cleanup
请勿在 32 位代码中尝试此操作,因为异步事件(信号等)可能会在 mov 之后和 fld 之前破坏堆栈上的值。
您的问题中不清楚的是 EAX 中的值是整数还是恰好是 32 位浮点值。如果它是整数,则必须在我的答案中将 FLD 替换为 FILD,以便在加载到 FPU 堆栈时将整数值转换为浮点值。
【讨论】:
FLD指令只能从内存中读取,所以需要将EAX的值保存到内存位置,然后进行内存上传。
a_memory_place dd ?
.
mov dword ptr [a_memory_place],eax
fld dword ptr [a_memory_place] ; loads a 32 bit data into ST(0)
相信这会有所帮助
【讨论】:
dword ptr 是 MASM,OP 标记为 NASM,这将是 mov dword 和 fld dword,没有 ptr 令牌。跨度>
[esp](或[ebp - something],如果您制作了堆栈框架)。或者push eax,就像迈克尔建议的那样。
fld dword ptr [eax]
此代码运行良好! 但是 eax 必须指向有效的 32 位实数! 如果您使用的是 64 位真实版本,请使用:
fld qword ptr [eax]
【讨论】: