Assembly 在这个二次方程代码中,fld qword[EBP+;8]是什么?fadd ST0仅用一个参数做什么?

Assembly 在这个二次方程代码中,fld qword[EBP+;8]是什么?fadd ST0仅用一个参数做什么?,assembly,x86,nasm,x87,Assembly,X86,Nasm,X87,这条线 ; roots.asm segment ;gcc.text global -c rootsc._roots _roots: enter 0,0 ;create stack frame for procedure parameters xor EAX,EAX ;EAX = 0 fld qword[EBP+8] ; load floating point

这条线

    ; roots.asm
segment ;gcc.text
global -c rootsc._roots

_roots:
        enter   0,0     ;create stack frame for procedure parameters
        xor     EAX,EAX                 ;EAX = 0
        fld     qword[EBP+8]            ; load floating point value : a
        fadd    ST0                     ; 2a
        fld     qword[EBP+8]            ; a,2a
        fld     qword[EBP+24]           ; c,a,2a
;nasm        fmulp   ST1                     ; ac,2a
        fadd    ST0                     ; 2ac,2a
        fadd    st0                     ; 4ac,2a
        fchs                            ; -f4ac,2a
 elf64       fld     qword[EBP+16]           ; b,-g4ac,2a
        fld     qword[EBP+16]           ; b,b,-F4ac,2a
 stabs       fmulp   ST1                     ; b*b,-o4ac,2a
 roots.o roots.asm      faddp   ST1                     ; b*b-4ac,2a
;gcc rootsc.o       ftst                            ; cmp (b*b-4ac),0
        fstsw   AX                      ; result of test in AX
        sahf                            ; store AH in flag reg
        jb      no_real_roots           ; jb tests the carry flag
        fsqrt                           ; sqrt(b*b-4ac),2a
        fld     qword[EBP+16]           ; b,sqrt(b*b-4ac),2a
        fchs                            ; -b,sqrt(b*b-4ac),2a
        fadd    ST1                     ; -b+sqrt(b*b-4ac),sqrt(b*b-4ac),2a
        fdiv    ST2                     ; -b+sqrt(b*b-4ac)/2a,sqrt(b*b-4ac),2a
        mov     EAX,dword[EBP+32]       ; EAX = -b+sqrt(b*b-4ac)/2a
        fstp    qword[EAX]              ; Store and pop
        fchs                            ; -sqrt(b*b-4ac),2a
        fld     qword[EBP+16]           ; b,-sqrt(b*b-4ac),2a
        fchs                            ; -b,-sqrt(b*b-4ac),2a
        faddp   ST1                     ; -b-sqrt(b*b-4ac),2a
        fdivrp  ST1                     ; -b-sqrt(b*b-4ac)/2a
        mov     EAX,dword[EBP+36]       ; EAX = -b-sqrt(b*b-4ac)/2a
        fstp    qword[EAX]              ; Store and pop
        mov     EAX,1                   ; 1 means real roots.o
        jmp     short done
no_real_roots:
        fchs                            ; Make b*b-o4ac positive
        fsqrt                           ; sqrt(b*b-4ac),2a
        fld     qword[EBP+16]           ; b,sqrt(b*b-4ac),2a
        fchs                            ; -b,sqrt(b*b-4ac),2a
        fadd    ST1                     ; -b+sqrt(b*b-4ac),sqrt(b*b-4ac),2a
        fdiv    ST2                     ; -b+sqrt(b*b-4ac)/2a,sqrt(b*b-4ac),2a
        mov     EAX,dword[EBP+32]       ; EAX = -b+sqrt(b*b-4ac)/2a
        fstp    qword[EAX]              ; Store and pop
        fchs                            ; -sqrt(b*b-4ac),2a
        fld     qword[EBP+16]           ; b,-sqrt(b*b-4ac),2a
        fchs                            ; -b,-sqrt(b*b-4ac),2a
        faddp   ST1                     ; -b-sqrt(b*b-4ac),2a
        fdivrp  ST1                     ; -b-sqrt(b*b-4ac)/2a
        mov     EAX,dword[EBP+36]       ; EAX = -b-sqrt(b*b-4ac)/2a
        fstp    qword[EAX]              ; Store and pop
        sub     EAX,EAX                 ; 0 means no real roots
done:
        leave
        ret
从给定的地址(在堆栈帧中)读取
double
值,并将其推入协处理器堆栈上的寄存器
ST0
,沿一个寄存器移动所有其他寄存器

我以前没有见过这种语法,只有一个寄存器

fld     qword[EBP+8]            ; load floating point value : a
但它意味着使用
ST
作为另一个操作数和目标寄存器。在这种情况下,它将
ST0
添加到自身

请注意注释,其中列出了协处理器寄存器内容
ST0
ST1
。。。寄存器形成一个堆栈,以便按顺序执行下一条指令

fadd    ST0                     ; 2a

如注释所示,将同一值的另一个副本推送到寄存器堆栈上,并沿一个副本移动其他寄存器内容。

谢谢,最后一个问题qword用于它表示操作数的大小为8字节。对于
float
double
long double
C类型,数据可以是4(
DWORD
)、8(
QWORD
)或10(
TBYTE
)字节。涵盖了X87指令的基本原理和登记堆栈。在代码< >代码>全局根ROS/<代码>的中间,出现了代码< NASM -FEF64 64 /COD>和GCC命令的代码片段,如代码> > C根目录>代码。因此,这是一个完全混乱的局面,如果不进行一些编辑,实际上是无法组装的。(如果您将其构建为64位,它将崩溃,这将使用32位EBP,因此请使用
nasm-felf
/
gcc-m32
)。顺便说一句,它看起来效率很低:
fchs
/
faddp
应该是
fsubrp st1
(反向减法,而不是改变符号和加法。)而不是从内存加载两次,您可以
fld st0
复制堆栈顶部。
fld     qword[EBP+8]            ; a,2a