Assembly 英特尔处理器上的浮点汇编

Assembly 英特尔处理器上的浮点汇编,assembly,x86,reverse-engineering,fpu,x87,Assembly,X86,Reverse Engineering,Fpu,X87,我一直在研究如何在32位intel机器上执行浮点运算。我已经反汇编了以下几行C代码,以获得编译器如何在汇编时翻译这些代码行 a = 13; b = 5; d = (float) a / (float) b; 下面是上述代码的反汇编版本: mov DWORD PTR [ebp-0x10],0xd mov DWORD PTR [ebp-0x14],0x5 fild DWORD PTR [ebp-0x10] fild DWORD PTR [ebp-0x14] fdivrp st(

我一直在研究如何在32位intel机器上执行浮点运算。我已经反汇编了以下几行C代码,以获得编译器如何在汇编时翻译这些代码行

a = 13;
b = 5;
d = (float) a / (float) b;
下面是上述代码的反汇编版本:

mov    DWORD PTR [ebp-0x10],0xd
mov    DWORD PTR [ebp-0x14],0x5
fild   DWORD PTR [ebp-0x10]
fild   DWORD PTR [ebp-0x14]
fdivrp st(1),st
fstp   DWORD PTR [ebp-0x18]

我感到困惑的是fdivrp和fstp指令。根据我阅读的内容,上面的代码将浮点除法的结果存储在st(1)寄存器上,然后弹出堆栈顶部,使st(1)成为顶部而不是st(0)。但是,下一条fstp指令将st(0)的内容存储到地址ebp-0x18所指向的内存位置,然后弹出堆栈,使st(1)成为顶部。我相信我误解了有关这些说明如何操作的文件,因为我的理解不会将结果存储在内存中。如果有人能解释这两条指令的具体操作方式,我将不胜感激。

浮点寄存器总是相对于当前栈顶寻址。因此,
st(0)
始终是堆栈顶部。
fdivrp st(1),st
将结果放置在
st(1)
中,然后立即弹出
st(0)
,因此堆栈仅保存一个项目,即包含结果的新的
st(0)
fstp
将其写入内存并将其从fpu堆栈中删除,使其为空。

堆栈的顶部始终称为st(0)。有到的链接,应该涵盖所有内容。除非您必须经常处理x87代码,否则我建议您不要在上面花费时间,除非它在实践中出现。x87已经过时,除了32位ABI仍然在
st(0)
中返回FP值。64位ABI使用SSE寄存器传递/返回浮点和双精度。如果你不介意打破与13年前硬件的兼容性(AMD Athlon XP是最后一个没有SSE2的CPU),32位代码可以编译为使用SSE/SSE2。Peter,我看到你经常提到32位ABI和64位ABI。请注意,不同的操作系统有不同的ABI,不太清楚您指的是哪一个,可能是Linux还是BDS?请注意,在32位Windows中,x87代码一点也不过时。这是否意味着fdivrp st(1),st会弹出st1到st0?文档说明,要弹出寄存器堆栈,处理器将ST(0)寄存器标记为空,并将堆栈指针(顶部)递增1。我发现这个短语很难理解。通过弹出,堆栈
TOP
会发生变化,并且由于寄存器索引是相对于
TOP
,所以以前称为
st(1)
的物理寄存器变为
st(0)
。不涉及数据移动。