标签: x87

基本FPU指令/堆栈概述?

我试图对x86上的浮点运算有一个基本的了解.我知道我们有一个带有堆栈的专用FPU,但是我没有找到关于堆栈在不同指令方面的行为方式的相关信息.

基本上,fpu寄存器的寻址让我很困惑.如果我参考st(#),我是在谈论一个特定的寄存器吗?或者它是从堆栈顶部偏移?

我想我的大多数问题都可以通过这个例子来回答:

如果我有一个空的FPU堆栈,并运行:

fld x
fld y
fmul st, st(1)
Run Code Online (Sandbox Code Playgroud)

结果会是:

ST(0) = y * x
ST(1) = x
Run Code Online (Sandbox Code Playgroud)

要么:

ST(0) = x * y
ST(1) = y
Run Code Online (Sandbox Code Playgroud)

注意,它们之间的差异是ST(1)中的值.

x86 assembly x87

3
推荐指数
1
解决办法
501
查看次数

这是sqrt函数中的一个错误

我创建了一个应用程序来计算64位范围内的素数,所以当我尝试使用i的sqrt函数计算64位数的平方根时,math.h发现答案是不准确的,例如当输入是~0ull答案应该是~0u但是我得到的是0x100000000哪个不对,所以我决定用汇编x86语言创建我自己的版本,看看这是不是一个bug,这是我的函数:

inline unsigned prime_isqrt(unsigned long long value)
{
    const unsigned one = 1;
    const unsigned two = 2;

    __asm
    {
        test dword ptr [value+4], 0x80000000
        jz ZERO
        mov eax, dword ptr [value]
        mov ecx, dword ptr [value + 4]

        shrd eax, ecx, 1
        shr  ecx, 1
        mov  dword ptr [value],eax 
        mov  dword ptr [value+4],ecx

        fild value
        fimul two
        fiadd one
        jmp REST
ZERO: 
        fild value
REST: 
        fsqrt
        fisttp value
        mov …
Run Code Online (Sandbox Code Playgroud)

c++ x86 assembly standard-library x87

3
推荐指数
1
解决办法
623
查看次数

如何将ST(0)移动到EAX?

Hullo,我正在学习x86 FPU汇编,我有一个简单的问题,我找不到答案:

如何将值从ST(0)(FPU堆栈顶部)移动到EAX

还有:
这段代码是否正确:

; multiply (dot) two vectors of 3 floats passed by pointers as arg 1 arg 2
; passings are ok I think, but not sure if multiplies-adds are ok

    push    ebp                                     
    mov     ebp, esp                                
    mov     eax, dword [ebp+8H]                     
    mov     edx, dword [ebp+0CH]                    

    fld     qword [eax]                             
    fmul    qword [edx]                             
    fld     qword [eax+4H]                          
    fmul    qword [edx+4H]                          
    fld     qword [eax+8H]                          
    fmul    qword [edx+8H]                          
    faddp   st1, st(0)                              
    faddp   st1, st(0)                            
    fstp    qword [ebp+10H]     ; here …
Run Code Online (Sandbox Code Playgroud)

x86 assembly fpu x87

3
推荐指数
1
解决办法
6589
查看次数

将常量值添加到x86中的xmm寄存器

我如何添加12注册xmm0(双)?

我可以这样做,但肯定必须有一个更简单的方法:

movsd xmm0, [ecx]

xor eax, eax
inc eax
cvtsi2sd xmm1, eax
addsd xmm0, xmm1

movsd [ecx], xmm0

还可以使用浮点x87指令执行此操作吗?

这对我不起作用:

fld dword ptr [ecx]
fld1
faddp
fstp dword ptr [ecx]

x86 assembly sse x87

3
推荐指数
1
解决办法
9063
查看次数

使用Newton-Raphson方法在x87 FPU上的立方根

我正在尝试使用8086处理器编写汇编程序,该处理器将找到数字的立方根.显然我使用的是浮点数.

基于Newton-Raphson方法的算法:

root := 1.0; 
repeat
     oldRoot := root;
     root := (2.0*root + x/(root*root)) / 3.0 
until ( |root – oldRoot| < 0.001;
Run Code Online (Sandbox Code Playgroud)

如何将(2*root + x)除以(root*root)?

.586
.MODEL FLAT
.STACK 4096

.DATA
root    REAL4   1.0
oldRoot REAL4   2.0
Two     REAL4   2.0
inttwo  DWORD   2
itThree DWORD   3
three   REAL4   3.0
x       DOWRD   27


.CODE
main    PROC
        finit           ; initialize FPU
        fld     root    ; root in ST
        fmul    two     ; root*two
        fadd    x       ; root*two+27

        fld     root    ; root …
Run Code Online (Sandbox Code Playgroud)

x86 assembly masm newtons-method x87

3
推荐指数
1
解决办法
643
查看次数

为什么x86 FP像无符号整数那样比较集CF,而不使用有符号条件?

英特尔指令参考中提供了以下文档以供参考COMISD

在操作数1(第一个操作数)的低四字比较双精度浮点值和操作数2(第二个操作数),并设定了ZFPFCF在EFLAGS标志寄存器根据结果(无序,大于,小于大于或等于)。

CF的标志点是不是真的在这里清除,因为它关系到算术运算的无符号整数。相反,文档关注的是按定义签名的浮点。我进行了一些实验,例如

mov rax, 0x123
movq xmm0, rax

mov rax, 0x124
movq xmm1, rax

ucomisd xmm0, xmm1 ;CF is set here like if
                    ;we would compare uints 0x123 and 0x124
Run Code Online (Sandbox Code Playgroud)

因此,当将操作数设置为双精度浮点时,该指令会将操作数设置为进位标志时,会将操作数视为无符号整数?

在我看来,这有点奇怪。

x86 assembly sse sse2 x87

3
推荐指数
1
解决办法
104
查看次数

Streaming SIMD Extensions是否取代了x87指令集?

我知道SSE是x87浮点指令的替代品,但x87 FPU仍然在现代CPU中实现,如Ivy-Bridge或Haswell?

SSE是否取代了x87指令集?

sse instruction-set x87

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

如何在 NASM 中将两个数字(整数和浮点数)相加?

我有这段代码,应该添加两个数字,一个浮点数(3.25)和一个整数(2)。

编辑:

extern _printf, _scanf
global _main
section .bss
  num1: resb 4
section .data
  format_num: db "%f", 10, 0
section .text
_main:

  mov dword [num1], __float32__(3.25)
  add num1,  2

  sub esp, 8
  fld dword [num1]
  mov dword [num1], eax
  fstp qword [esp]
  push format_num
  call _printf
  add esp, 12

ret
Run Code Online (Sandbox Code Playgroud)

我得到的输出是:

test.asm:11:错误:操作码和操作数的组合无效

我期望的输出是:

5.250000

x86 assembly gcc nasm x87

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

为什么 FLD m80fp 不会引发 SNaN 输入的异常,而 double 或 float 的 FLD 可以?

以下是使用FLD时可能出现的异常:

  • #IS 发生堆栈下溢或溢出。
  • #IA 源操作数是 SNaN。如果源操作数是双扩展精度浮点格式(FLD m80fp 或 FLD ST(i)),则不会发生。
  • #D 源操作数是一个非正规值。如果源操作数是双扩展精度浮点格式,则不会发生。

为什么 #IA 异常“如果源操作数是双扩展精度浮点格式,则不会发生”?

我认为双精度浮点和双扩展精度浮点格式基本相同。两者都能够编码 SNaN。

这种差异是否有任何合乎逻辑的原因,或者只是它的方式?

floating-point x86 assembly x87

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

x87 可以对 UNsigned QUADword 整数执行精确除法吗?

8086/8087/8088 宏汇编语言参考手册 (c) 1980 Intel Corporation 提到(重点是我的):

... 8087 提供了非常好的实数系统近似值。然而,重要的是要记住,它不是精确的表示,并且实数的算术本质上是近似的。
相反,同样重要的是,8087 确实对其实数的整数子集执行精确算术。也就是说,对两个整数进行运算会返回精确的积分结果,前提是真实结果是整数并且在 range 内

最近的手册更加简洁(强调他们的):

IA 处理器...它们可以处理最多 18 位的十进制数,而不会出现舍入错误,对大至 2^64(或 10^18)的整数执行精确算术。

FPU 支持的整数数据类型包括有符号字(16 位)、有符号双字(32 位)和有符号 qword(64 位)。从来没有提到过 UNsigned。事实上,FPU 的一切都带有符号性,甚至支持带符号零(+0 和 -0)。
那么,是否可以使用 FPU 将几个无符号64 位数字相除并得到精确的商和余数?

对于几个有符号64 位数字的除法,我编写了下面的代码。商看起来不错,但余数总是返回零。为什么是这样?

; IN (edx:eax,ecx:ebx) OUT (edx:eax,ecx:ebx,CF)
FiDiv:  push    edi ecx ebx edx eax
        mov     edi, esp
        fninit
        fild    qword [edi]     ; Dividend
        fild    qword [edi+8]   ; Divisor
        fld
        fnstcw  [edi]
        or      word [edi], 0C00h ; Truncate Towards …
Run Code Online (Sandbox Code Playgroud)

x86 assembly rounding integer-division x87

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