【发布时间】:2019-04-19 07:03:15
【问题描述】:
; 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
【问题讨论】:
-
ray.masmcode.com/tutorial/index.html 涵盖了 x87 指令的基本功能以及寄存器堆栈。
-
似乎有
nasm -felf64和gcc 命令的片段散布在您的代码中,例如-c roots在global _roots指令中间。所以这完全是一团糟,如果没有一些编辑,实际上不会组装。 (如果你将它构建为 64 位,它会崩溃,这使用 32 位 EBP 所以使用nasm -felf/gcc -m32)。顺便说一句,它看起来效率低下:fchs/faddp应该是fsubrp st1(反向减去而不是更改符号和添加。)而不是从内存中加载两次,您可以fld st0复制顶部堆栈。