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