标签: x87

在汇编中添加浮点/双精度数

我试图尝试内联汇编,我试图在内联汇编中添加十进制数字(不,不是整数).问题是,当我调用以下函数时:

inline double ADD(double num1, double num2) {
  double res;
_asm{

    push eax; push the former state of eax onto stack
    mov eax, num1;
    add eax, num2;
    mov res, eax;
    pop eax; restore the former state of eax now that we are done   
     }  return res;}
Run Code Online (Sandbox Code Playgroud)

编译器抱怨内联汇编中的操作数大小不合适(除了push和pop指令行之外的所有汇编行).所以我必须更改为整数类型,例如unsigned long,然后它可以工作,但当然只支持整数类型; 小数结果四舍五入.

有没有办法添加允许像8.4这样的十进制结果的汇编?

c x86 assembly x87

6
推荐指数
2
解决办法
1万
查看次数

寻找接近的浮点数之间的“离散”差异

假设我有两个浮点数xy,它们的值非常接近。

计算机上可以表示离散数量的浮点数,因此我们可以按升序枚举它们:f_1, f_2, f_3, ...x我希望找到和在此列表中的距离y(即它们是 1、2、3、... 还是n离散步长?)

是否可以仅使用算术运算(+-*/)而不查看二进制表示来做到这一点?我主要感兴趣的是它在 x86 上的工作原理。

假设 和y > x之间x只有y几步(例如 < 100),下面的近似值是否正确?(可能不会 ...)

(y-x) / x / eps
Run Code Online (Sandbox Code Playgroud)

这里eps表示机器 epsilon。(机器 epsilon 是 1.0 和下一个最小浮点数之间的差。)

floating-point numerical x87

5
推荐指数
1
解决办法
963
查看次数

你如何从SSE中获得最大速度?

MXCSR之类的东西有哪些最佳设置?哪种舍入模式最快?什么处理器?启用信号NaN是否更快,以便在计算结果为nan时获得通知,或者这会导致非NaN计算的速度减慢?

总之,如何从紧密的内部SSE循环中获得最大速度?

任何相关的x87浮点速度建议也欢迎.

optimization x86 assembly sse x87

5
推荐指数
1
解决办法
447
查看次数

x87 FPOP和FCOM指令 - 这些如何工作?

我的任务是在混合C/ASM中编写一个简单的应用程序,它必须使用数学协处理器.

有一个函数柱面(float x,float y,float z),如果给定的点位于柱面内,则返回1(柱面的底边为x = 0,y = 0,半径= 5,高度= 10),如果不是,则为0.

所以,看起来很简单.检查z是否在<0,10>范围内,然后检查x ^ 2 + y ^ 2 <25.

但是我对x87的了解是零.

这就是我写的一切.

_cylinder PROC

push ebp
mov ebp, esp
sub esp,8 ; I can't use .data in the application, so I reserve some space on the stack for numbers 10 and 25
mov [esp],10
mov [esp+4],25

finit
fldz
fld [ebp+8]

    ;here i get stuck 

add esp, 8
pop ebp
_cylinder ENDP
Run Code Online (Sandbox Code Playgroud)

所以我卡住了.所以,我试着找到我可以在应用程序中使用的指令.在那里我卡住了,因为我在网上找到的每个教程/指令列表写得非常糟糕,我几乎无法理解任何东西.

问题是,当我从数学协处理器弹出一些东西时会发生什么?我在哪里可以找到弹出值?它如何从80位值转换为32位值(当然如果有)另一个问题是,FCOM(用于pop变体的FCOMP)如何工作?它比较什么(st0到st1或st1到st0?),在哪里可以看到值是小/等于/更大?

谢谢你的帮助!

c x86 assembly x87

5
推荐指数
1
解决办法
1630
查看次数

是否有未签名的x87 FILD和SSE CVTSI2SD指令?

我想在GHC Haskell编译器中实现C的uint-to- doublecast 的等价物.我们已经实现了int-到- double使用FILDCVTSI2SD.是否有这些操作的无符号版本,或者我应该uint将转换前的最高位置零(从而丢失范围)?

floating-point assembly sse x87

5
推荐指数
2
解决办法
894
查看次数

为什么 80x87 指令集使用“基于堆栈”的设计?

回到 Intel 最初设计 8087 时,他们为什么选择将浮点寄存器组织为堆栈?从这样的设计中可以获得什么可能的优势?与允许将任意寄存器用作源和目标操作数相比,它似乎更不灵活且更难使用。

x86 assembly instruction-set cpu-architecture x87

5
推荐指数
1
解决办法
250
查看次数

如何反编译这个x87装配计算?

我正在反转的程序在浮点数和8字节整数之间进行简单的乘法运算:

section .data

va: dt 1.4426950408889634074
vb: dd 0x42424242
    dd 0x41414141

section .text
global main

main:
    fld tword[va]
    fmul qword[vb]
    ret
Run Code Online (Sandbox Code Playgroud)

gdb下的结果:

Breakpoint 1, 0x08048360 in main ()
(gdb) x/i $eip
0x8048360 <main>:       fld    TBYTE PTR ds:0x804953c
0x8048366 <main+6>:     fmul   QWORD PTR ds:0x8049546
0x804836c <main+12>:    ret
(gdb) x/gx 0x8049546
0x8049546 <vb>: 0x4141414142424242
(gdb) si
0x08048366 in main ()
0x0804836c in main ()
(gdb) info float
=>R7: Valid   0x4014c726039c95268dc4 +3262848.902912714389
Run Code Online (Sandbox Code Playgroud)

我正在尝试在C(相同的32位环境)中重新创建此程序:

#include <stdio.h>

int main() {

    unsigned long long vb = …
Run Code Online (Sandbox Code Playgroud)

c floating-point assembly reverse-engineering x87

5
推荐指数
1
解决办法
209
查看次数

如何用扩展的gcc程序集指定x87 FPU堆栈的破坏底部?

在我们的代码库中,我发现这个代码片段用于在x87上进行快速,向负无限1舍入:

inline int my_int(double x)
{
  int r;
#ifdef _GCC_
  asm ("fldl %1\n"
       "fistpl %0\n"
       :"=m"(r)
       :"m"(x));
#else
  // ...
#endif
  return r;
}
Run Code Online (Sandbox Code Playgroud)

我不是非常熟悉GCC扩展汇编语法,但是从我从文档中收集到的内容:

  • r 必须是一个记忆位置,我在写回东西;
  • x 必须是一个内存位置,数据来自哪里.
  • 没有clobber规范,因此编译器可以放心,在代码片段的末尾,寄存器就像他离开时一样.

现在,来回答我的问题:最终FPU堆栈是平衡的,但是如果所有8个位置都已经在使用并且我已经溢出呢?编译器如何知道它不能信任ST(7)它离开它的位置?应该添加一些clobber吗?

编辑我试图st(7)在clobber列表中指定它似乎影响codegen,现在我将等待对此事实的一些确认.


作为旁注:看看lrintglibc和MinGW 中的准系统的实现,我看到了类似的东西

__asm__ __volatile__ ("fistpl %0"
                      : "=m" (retval)
                      : "t" (x)
                      : "st");
Run Code Online (Sandbox Code Playgroud)

我们要求输入直接放在哪里ST(0)(避免这种情况无用fldl); 什么是"st"clobber?文档似乎只提到t(即堆栈的顶部).


  1. 是的,它取决于当前的舍入模式,在我们的应用程序中应该总是"朝向负无穷大".

c x86 assembly gcc x87

5
推荐指数
1
解决办法
440
查看次数

使用x87 FPU将浮点转换为带截断的整数,而不是舍入

所述FISTP指令改变0.75至1(因为四舍五入)

我希望0.75变成0而不是1.

是否有FIST/FISTP的替代方法可以截断而不是舍入

assembly nasm x87

5
推荐指数
2
解决办法
2146
查看次数

为什么 MinGW GCC 对 atan2、cos、exp 和 sin 使用 x87 80 位 FP 库代码?

我在从 Intel 2023 和 MSC Visual C++ 2022 移植工作数字代码时遇到一个奇怪的问题。使用 GCC 编译的代码非常准确(太准确),因为某些库调用以完整的 80 位浮点精度工作 - 特别是 sqrt、sin 和 cos。我可以通过使用 TUI 跟踪 gdb 的库调用来反汇编库代码执行来验证这一点。

它也出现在基准计时中,因为 x87 atan2、cos、exp 和 sin 都约为 100 个周期,而 sqrt 约为 80 个周期。SSE/AVX2 代码的相应时序低于 50 个周期,大部分在 20-30 个周期左右。

奇怪的是 tan、atan使用 AVX2 编译的。但 cos、sin、sqrt 和 atan2 在 GCC 系统库中使用旧版 x87 代码。我已经在 32 位端口和 64 位版本上尝试过此操作,并且都遇到了相同的问题。我是海湾合作委员会的新手,所以我可能忽略了一些事情。我在 Windows 上使用默认的 MinGW 端口版本 13.1.0 (MinGW-W64 i686-ucrt-posix-dwarf),它可能有其自身的特点。

顺便说一句,我刚刚注意到 MSC 2022 有时会编码 x87 sqrt,即使启用了所有 gofaster 优化和 AVX2 代码,因为这也是我之前没有注意到的基准计时中的异常值。Intel 将其编译为本机 sqrtsd,因此速度要快得多。我回到 MSC x86 进行内联汇编,以确认 x87 …

floating-point gcc mingw avx x87

5
推荐指数
0
解决办法
80
查看次数