Assembly asm(fpu)规范化-如何优化它
我已经编写了一些x86 asm-fpu例程 规范化一个由三个浮点数组成的向量-就是这样Assembly asm(fpu)规范化-如何优化它,assembly,x86,sse,fpu,Assembly,X86,Sse,Fpu,我已经编写了一些x86 asm-fpu例程 规范化一个由三个浮点数组成的向量-就是这样 _asm_normalize10:; Function begin push ebp ; 002E _ 55 mov ebp, esp ; 002F _ 89. E5 mov eax, dword [ebp+8H]
_asm_normalize10:; Function begin
push ebp ; 002E _ 55
mov ebp, esp ; 002F _ 89. E5
mov eax, dword [ebp+8H] ; 0031 _ 8B. 45, 08
fld dword [eax] ; 0034 _ D9. 00
fmul st0, st(0) ; 0036 _ DC. C8
fld dword [eax+4H] ; 0038 _ D9. 40, 04
fmul st0, st(0) ; 003B _ DC. C8
fld dword [eax+8H] ; 003D _ D9. 40, 08
fmul st0, st(0) ; 0040 _ DC. C8
faddp st1, st(0) ; 0042 _ DE. C1
faddp st1, st(0) ; 0044 _ DE. C1
fsqrt ; 0046 _ D9. FA
fld1 ; 0048 _ D9. E8
fdivrp st1, st(0) ; 004A _ DE. F1
fld dword [eax] ; 004C _ D9. 00
fmul st(0), st1 ; 004E _ D8. C9
fstp dword [eax] ; 0050 _ D9. 18
fld dword [eax+4H] ; 0052 _ D9. 40, 04
fmul st(0), st1 ; 0055 _ D8. C9
fstp dword [eax+4H] ; 0057 _ D9. 58, 04
fld dword [eax+8H] ; 005A _ D9. 40, 08
fmulp st1, st(0) ; 005D _ DE. C9
fstp dword [eax+8H] ; 005F _ D9. 58, 08
pop ebp ; 0062 _ 5D
ret ; 0063 _ C3
; _asm_normalize10 End of function
[这是我的代码;-)它可以工作,并且经过我的测试]
我对x86汇编不太了解,我想找一些
优化上述(纯fpu旧asm,尤其是不带sse)
但要比上面优化一些)
特别是,我想知道上面的代码是否有些蹩脚:
我在fpu堆栈上加载x y z向量,然后计数1/sqrt(x*x+y*y+z*z)
然后再次从ram中加载x y z并乘以值,然后存储-
这是次优化吗?我应该只加载一次x y z(而不是两次)
然后将其保持在fpu堆栈计数上,然后在末尾存储?您可以完全按照您的建议执行,并且只加载一次
x
、y
和z
。这似乎是有帮助的。除此之外,假设你仍然不想使用近似平方根逆技巧,我看不出有什么机会
未测试:
; load everything
fld dword [eax]
fld dword [eax+4]
fld dword [eax+8]
; square and add
fld st(2)
fmul st(0), st(0)
; (see diagram 1 for fpu stack)
fld st(2)
fmul st(0), st(0)
; (see diagram 2 for fpu stack)
faddp st(1), st(0)
; (see diagram 3 for fpu stack)
fld st(1)
fmul st(0), st(0)
faddp st(1), st(0)
; (see diagram 4 for fpu stack)
; calculate inverse sqrt
fsqrt
fld1
fdivrp st(1), st(0)
; scale
fmul st(1), st(0)
fmul st(2), st(0)
fmulp st(3), st(0)
; store
fstp dword [eax+8]
fstp dword [eax+4]
fstp dword [eax]
图1:
st3: x
st2: y
st1: z
st0: x * x
图2:
st4: x
st3: y
st2: z
st1: x * x
st0: y * y
图3:
st3: x
st2: y
st1: z
st0: x * x + y * y
图4:
st3: x
st2: y
st1: z
st0: x * x + y * y + z * z
您可以完全按照您的建议执行并只加载一次
x
、y
和z
。这似乎是有帮助的。除此之外,假设你仍然不想使用近似平方根逆技巧,我看不出有什么机会
未测试:
; load everything
fld dword [eax]
fld dword [eax+4]
fld dword [eax+8]
; square and add
fld st(2)
fmul st(0), st(0)
; (see diagram 1 for fpu stack)
fld st(2)
fmul st(0), st(0)
; (see diagram 2 for fpu stack)
faddp st(1), st(0)
; (see diagram 3 for fpu stack)
fld st(1)
fmul st(0), st(0)
faddp st(1), st(0)
; (see diagram 4 for fpu stack)
; calculate inverse sqrt
fsqrt
fld1
fdivrp st(1), st(0)
; scale
fmul st(1), st(0)
fmul st(2), st(0)
fmulp st(3), st(0)
; store
fstp dword [eax+8]
fstp dword [eax+4]
fstp dword [eax]
图1:
st3: x
st2: y
st1: z
st0: x * x
图2:
st4: x
st3: y
st2: z
st1: x * x
st0: y * y
图3:
st3: x
st2: y
st1: z
st0: x * x + y * y
图4:
st3: x
st2: y
st1: z
st0: x * x + y * y + z * z
代码是这样的,只写一次,从不读。任何调试器显示操作码,都不会自动生成好的注释。考虑一个赏金,让用户花时间来逆向工程。你错了,它显然被铭记,虽然ASM知识是需要的代码,就像这是写一次,从不读。任何调试器显示操作码,都不会自动生成好的注释。考虑一个赏金,让用户花时间来逆向工程。你错了,它被简单地铭记,虽然ASM知识是必需的,我会测试它。我不知道fld st(2)助记符。您是否知道一种只从(fpu)堆栈获取(pop)编号的方法(无需其他操作)?至于“carmack’s”技巧,我测量了它,这是85个周期(在c中,不是asm测试),所以稍微快一点(可能重新编写为asm,它会更快),将尝试它l8er-也将返回到前面提到的RaySphereIntersection例程和sse-但后来(还没有到那里)TNxmuch@grungefightr你这是什么意思“仅从S堆栈中获取编号”?已编辑。我的意思是pop,一些代码我试图在没有其他操作的情况下编写所需的pop(如stp-仅pop而不存储;-)@Grungfightr
fstp st(0)
pops一个,您可以使用fcompp
弹出两个(更改fpu条件代码,但它们很少使用)@Grungfightr它存储到条目中,然后它会弹出,所以这不是问题。TNX,我会测试它。我不知道fld st(2)助记符。你知道可能有一种方法只从(fpu)堆栈中获取(pop)数字(没有其他操作)?至于“carmack”技巧,我测量了它,这是85个周期(在c中,没有经过asm测试),所以稍微快一点(可能重新编写为asm会更快),将尝试l8er-也将返回到之前提到的RaySphereIntersection例程和sse-但后来(尚未到达)TNxmuch@grungefightr“仅从堆栈中获取数字”是什么意思?已编辑。我是指pop,一些代码我试图在没有其他操作的情况下编写所需的pop(如stp-仅弹出而不存储;-)@Grungfightrfstp st(0)
pops one,您可以使用fcompp
弹出两个(更改fpu条件代码,但它们很少被使用)。@Grungfightr它存储到条目,然后无论如何弹出,所以这不是问题。