概述
【篇首语】这里的逆向分析不是机械中的反求工程(抄数),而是软件中的逆向工程,旨在研究软件内部代码实现机制。我在这里要说明一下,软件逆向不在软件使用的许可范围之内,仅可以作为研究软件实现功能的一种方法。
另外,我不是计算机专业的,软件逆向这种高技术难度的事情我做不到,只是看到论坛上有人发了一个UG的一个函数逆向分析,让我大开眼界,我觉得可以拿出来让大家也开开眼界!
本文仅是转载帖子,不承担责任,有什么问题请联系原作者!本贴仅作研究之用!
原帖:http://hi.baidu.com/xusir98/blog/item/269d9eaf17860ac07dd92a77.html
作者:xusir98
===================================================================
注: 按F5 快捷健是IDA 一个很好用的插件功能, 能大大减少逆向程序员的工作强度,
但是对于一些复杂的逻辑处理的还是不很好
extern void UF_MTX3_rotate_about_axis (
const double rotation_axis[ 3 ],
double rotation_angle,
double mtx[ 9 ] );
const double | rotation_axis[ 3 ] | Input | Vector of the rotation axis |
double | rotation_angle | Input | Angle of the rotation (in radians) |
double | mtx[ 9 ] | Output | Rotation Matrix |
UF_MTX3_rotate_about_axis 是UgOpen 里的一个输出旋转矩阵的函数,
他输入一个旋转轴, 一个角度, 输出一个旋转用的3 维矩阵
用 IDA 打开 libufun.dll
找到 UF_MTX3_rotate_about_axis
经更改调用函数参数显示如下 :
; int __cdecl UF_MTX3_rotate_about_axis(int rotation_axis, double rotation_angle, int mtx)
public _UF_MTX3_rotate_about_axis
_UF_MTX3_rotate_about_axis proc near ; DATA XREF: .rdata:off_1033A6E8o
var_10= qword ptr -10h
rotation_axis= dword ptr 8
rotation_angle= qword ptr 0Ch
mtx = dword ptr 14h
push ebp
mov ebp, esp
mov eax, [ebp+mtx]
fld [ebp+rotation_angle] ; 把传进来的参数放入 st0 中
mov ecx, [ebp+rotation_axis]
push eax
push ecx
sub esp, 8 ; 抬高栈 8 个字节
fstp [esp+10h+var_10] ; 将 st0 的值放入抬高栈的空间里
; const double rotation_axis[ 3 ],
; double rotation_angle,
; double mtx[ 9 ] )
call ds:__imp_?MTX3_rot_about_axis@@YAXNPBUVEC3_s@@PAUMTX3_s@@@Z ;
; 调用 NX 内核函数
; 注意参数位置调换过
add esp, 10h ; c 调用约定 , 将栈降低 16 个字节
pop ebp
retn
_UF_MTX3_rotate_about_axis endp
按下 F5 显示如下
void __cdecl UF_MTX3_rotate_about_axis(const struct VEC3_s *rotation_axis, double rotation_angle, struct MTX3_s *mtx)
{
MTX3_rot_about_axis(rotation_angle, rotation_axis, mtx);
}
可见 UF_MTX3_rotate_about_axis 调用了 MTX3_rot_about_axis, 并且把参数的位置更改变化了
MTX3_rot_about_axis 这个函数在 libugmath.dll 里
同样用 IDA 打开 libugmath.dll
找到 MTX3_rot_about_axis 函数
显示如下 :
; void __cdecl MTX3_rot_about_axis(double rotation_angle, double *rotation_axis, const struct MTX3_s *mtx)
public ?MTX3_rot_about_axis@@YAXNPBUVEC3_s@@PAUMTX3_s@@@Z
?MTX3_rot_about_axis@@YAXNPBUVEC3_s@@PAUMTX3_s@@@Z proc near
; CODE XREF: ARC_SPLINE_ask_bisector_of_inscribed_angle(VEC3_s *,VEC3_s *,PNT3_s *,VEC3_s *,double,double *,double *,int *,VEC3_s *,PLN3_s *)+169p
; ARC_SPLINE_cre_matrix_of_rotation_around_axis(VEC3_s *,double,MTX3_s *)+1Ap ...
var_30= qword ptr -30h
var_28= qword ptr -28h
unit_vec= qword ptr -20h
magnitude= qword ptr -8
rotation_angle= qword ptr 8
rotation_axis= dword ptr 10h
mtx = dword ptr 14h
push ebp
mov ebp, esp
sub esp, 20h
fld ds:__real@3ddb7cdfd9d7bdbb ; 参数 2, 压入 st0
mov edx, [ebp+rotation_axis]
lea eax, [ebp+unit_vec]
push eax ; 参数 4
lea ecx, [ebp-8]
push ecx ; 参数 3
sub esp, 8
fstp [esp+30h+var_30] ; 参数 2, 从 st0 弹出
push edx ; 参数 1
call ?VEC3_unitize@@YAHPBUVEC3_s@@NPANPAU1@@Z ; VEC3_unitize(VEC3_s const *,double,double *,VEC3_s *)
add esp, 14h
test eax, eax
jz short loc_201CBCB6
fld [ebp+rotation_angle]
fsin
fld [ebp+rotation_angle]
fcos
jmp short loc_201CBCC2
; ---------------------------------------------------------------------------
loc_201CBCB6: ; CODE XREF: MTX3_rot_about_axis(double,VEC3_s const *,MTX3_s *)+28j
fld ds:__real@0000000000000000
fld ds:__real@3ff0000000000000
loc_201CBCC2: ; CODE XREF: MTX3_rot_about_axis(double,VEC3_s const *,MTX3_s *)+34j
mov eax, [ebp+mtx] ; EAX
fxch st(1)
sub esp, 10h
fstp [esp+30h+var_28]
lea ecx, [ebp+unit_vec] ; ECX
fstp [esp+30h+var_30]
call sub_201CB3C0
add esp, 10h
mov esp, ebp
pop ebp
retn
?MTX3_rot_about_axis@@YAXNPBUVEC3_s@@PAUMTX3_s@@@Z endp
按下 F5 显示如下 :
void __cdecl MTX3_rot_about_axis(double rotation_angle, double *rotation_axis, const struct MTX3_s *mtx)
{
double fCos; // st6@2
double fSin; // st7@2
double unit_vec[3]; // [sp+10h] [bp-20h]@1
double magnitude; // [sp+28h] [bp-8h]@1
if ( VEC3_unitize(rotation_axis, 1.0e-10, &magnitude, unit_vec) )
{
fSin = sin(rotation_angle);
fCos = cos(rotation_angle);
}
else
{
fSin = 0.0;
fCos = 1.0;
}
sub_201CB3C0(mtx, unit_vec, fCos, fSin);
}
可见他先调用 VEC3_unitize 函数看看输入的矢量是否是初始话的 , 如果初始化失败 , 就
fSin = 0.0;
fCos = 1.0;
然后调用 sub_201CB3C0 这个子函数
分析 VEC3_unitize 函数
; int __cdecl VEC3_unitize(double *rotation_axis, double a2, double *magnitude, double *unit_vec)
public ?VEC3_unitize@@YAHPBUVEC3_s@@NPANPAU1@@Z
?VEC3_unitize@@YAHPBUVEC3_s@@NPANPAU1@@Z proc near
; CODE XREF: ARC_SPLINE_ask_3pts_collinearity_3d(PNT3_s *,PNT3_s *,PNT3_s *,double *,int *)+D5p
; ARC_SPLINE_adjust_vec_on_pln(uchar,VEC3_s *,VEC3_s *)+44p ...
var_8= qword ptr -8
rotation_axis= dword ptr 8
a2 = qword ptr 0Ch
magnitude= dword ptr 14h
unit_vec= dword ptr 18h
push ebp
mov ebp, esp
sub esp, 8
mov eax, ds:__imp_?MACH__checking_level@@3HA ; int MACH__checking_level
cmp dword ptr [eax], 0
push esi
mov esi, [ebp+rotation_axis]
jle short loc_201DB4EE
fld qword ptr [esi]
fabs
fcomp ds:__real@43e158e460913d00
fnstsw ax
test ah, 5
jp short loc_201DB4D9
fld qword ptr [esi+8]
fabs
fcomp ds:__real@43e158e460913d00
fnstsw ax
test ah, 5
jp short loc_201DB4D9
fld qword ptr [esi+10h]
fabs
fcomp ds:__real@43e158e460913d00
fnstsw ax
test ah, 5
jnp short loc_201DB4EE
loc_201DB4D9: ; CODE XREF: VEC3_unitize(VEC3_s const *,double,double *,VEC3_s *)+23j
; VEC3_unitize(VEC3_s const *,double,double *,VEC3_s *)+35j
push offset aVec3_is_finite ; "VEC3_is_finite (u)"
push 44h
push offset aDUgnx30Sand_16 ; "D://ugnx30//sandbox//src//ugmath//no//ind//vec"...
call ds:__imp_?ERROR_assertion_failed@@YAXPBDH0@Z ; ERROR_assertion_failed(char const *,int,char const *)
add esp, 0Ch
loc_201DB4EE: ; CODE XREF: VEC3_unitize(VEC3_s const *,double,double *,VEC3_s *)+12j
; VEC3_unitize(VEC3_s const *,double,double *,VEC3_s *)+47j
fld qword ptr [esi+10h]
fld qword ptr [esi+8]
fld qword ptr [esi]
fld st
fmul st, st(1)
fstp [ebp+var_8]
fstp st
fld st
fmul st, st(1)
fld st(2)
fmul st, st(3)
faddp st(1), st
fadd [ebp+var_8]
fabs
fld [ebp+a2]
fmul [ebp+a2]
fcompp
fnstsw ax
fstp st
test ah, 1
fstp st
jz short loc_201DB568
fld qword ptr [esi+10h]
mov ecx, [ebp+magnitude]
fld qword ptr [esi+8]
mov eax, 1
fld st
fmul st, st(1)
fld st(2)
fmul st, st(3)
faddp st(1), st
fadd [ebp+var_8]
fsqrt
fstp st(2)
fstp st
fld st
fstp qword ptr [ecx]
mov ecx, [ebp+unit_vec]
fdivr ds:__real@3ff0000000000000
fld st
fmul qword ptr [esi]
fstp qword ptr [ecx]
fld st
fmul qword ptr [esi+8]
fstp qword ptr [ecx+8]
fmul qword ptr [esi+10h]
pop esi
fstp qword ptr [ecx+10h]
mov esp, ebp
pop ebp
retn
; ---------------------------------------------------------------------------
loc_201DB568: ; CODE XREF: VEC3_unitize(VEC3_s const *,double,double *,VEC3_s *)+8Fj
fld ds:__real@0000000000000000
mov edx, [ebp+magnitude]
mov ecx, [ebp+unit_vec]
fstp qword ptr [edx]
fld ds:__real@0000000000000000
xor eax, eax
fstp qword ptr [ecx]
pop esi
fld ds:__real@0000000000000000
fstp qword ptr [ecx+8]
fld ds:__real@0000000000000000
fstp qword ptr [ecx+10h]
mov esp, ebp
pop ebp
retn
?VEC3_unitize@@YAHPBUVEC3_s@@NPANPAU1@@Z endp
F5 后有 :
int __cdecl VEC3_unitize(double *rotation_axis, double a2, double *magnitude, double *unit_vec)
{
int result; // eax@7
double v5; // st5@7
double v6; // [sp+4h] [bp-8h]@6
if ( MACH__checking_level > 0 )
{
if ( fabs(*rotation_axis) >= 1.0e19 || fabs(rotation_axis[1]) >= 1.0e19 || fabs(rotation_axis[2]) >= 1.0e19 )
ERROR_assertion_failed("D://ugnx30//sandbox//src//ugmath//no//ind//vec3.c", 68, "VEC3_is_finite (u)");
}
v6 = *rotation_axis * *rotation_axis;
if ( a2 * a2 >= fabs(rotation_axis[1] * rotation_axis[1] + rotation_axis[2] * rotation_axis[2] + v6) )
{ // 如果矢量的平方和接近与 0, 就返回错误
*magnitude = 0.0;
result = 0;
*unit_vec = 0.0;
unit_vec[1] = 0.0;
unit_vec[2] = 0.0;
}
else
{
result = 1;
v5 = sqrt(rotation_axis[1] * rotation_axis[1] + rotation_axis[2] * rotation_axis[2] + v6);
*(_QWORD *)magnitude = *(_QWORD *)&v5;
*unit_vec = 1.0 / v5 * *rotation_axis;
unit_vec[1] = 1.0 / v5 * rotation_axis[1];
unit_vec[2] = 1.0 / v5 * rotation_axis[2];
}
return result;
}
他做的工作是如果矢量的平方和接近与 0, 就返回错误 , 否则就返回一个模化好的矢量
if ( MACH__checking_level > 0 )
{
if ( fabs(*rotation_axis) >= 1.0e19 || fabs(rotation_axis[1]) >= 1.0e19 || fabs(rotation_axis[2]) >= 1.0e19 )
ERROR_assertion_failed("D://ugnx30//sandbox//src//ugmath//no//ind//vec3.c", 68, "VEC3_is_finite (u)");
}
的意思是当机器的检测权限大于 0 时 , 就报出诊断错误
接下来就看看 sub_201CB3C0 这个子函数到底做了些什么吧 !
这个子函数是我逆向最久的一个函数 , 因为这个函数按 F5 实效了 , 于是我把浮点的栈一句一句的模拟出来
最后得出公式 :
; void __usercall sub_201CB3C0(const struct MTX3_s *EAX<eax>, double *ECX<ecx>, double fCos, double fSin)
sub_201CB3C0 proc near ; CODE XREF: MTX3_rot_about_axis(double,VEC3_s const *,MTX3_s *)+54p
var_20= qword ptr -20h
var_18= qword ptr -18h
var_10= qword ptr -10h
var_8= qword ptr -8
fCos= qword ptr 8
fSin= qword ptr 10h
push ebp
mov ebp, esp ; (eax->mtx, ecx->unit_vec, fCos, fSin)
sub esp, 20h
fld qword ptr [ecx] ; ecx[0]
fld qword ptr [ecx+8] ; ecx[1]
fld qword ptr [ecx+10h] ; ecx[2]
fld ds:__real@3ff0000000000000 ; st0:1
; st1:ecx[2]
; st2:ecx[1]
; st3:ecx[0]
; st4:
; st5:
; st6:
; st7:
; ~~~~~~~~~~~~
fsub [ebp+fCos] ; st0:1-fCos
; st1:ecx[2]
; st2:ecx[1]
; st3:ecx[0]
; st4:
; st5:
; st6:
; st7:
; ~~~~~~~~~~~~
fld st ; st0:1-fCos
; st1:1-fCos
; st2:ecx[2]
; st3:ecx[1]
; st4:ecx[0]
; st5:
; st6:
; st7:
; ~~~~~~~~~~~~
fmul st, st(4) ; st0:(1-fCos)*ecx[0]
; st1:1-fCos
; st2:ecx[2]
; st3:ecx[1]
; st4:ecx[0]
; st5:
; st6:
; st7:
; ~~~~~~~~~~~~
fld st(1) ; st0:1-fCos
; st1:(1-fCos)*ecx[0]
; st2:1-fCos
; st3:ecx[2]
; st4:ecx[1]
; st5:ecx[0]
; st6:
; st7:
; ~~~~~~~~~~~~
fmul st, st(4) ; st0:(1-fCos)*ecx[1]
; st1:(1-fCos)*ecx[0]
; st2:1-fCos
; st3:ecx[2]
; st4:ecx[1]
; st5:ecx[0]
; st6:
; st7:
; ~~~~~~~~~~~~
fld st(1) ; st0:(1-fCos)*ecx[0]
; st1:(1-fCos)*ecx[1]
; st2:(1-fCos)*ecx[0]
; st3:1-fCos
; st4:ecx[2]
; st5:ecx[1]
; st6:ecx[0]
; st7:
; ~~~~~~~~~~~~
fmul st, st(5) ; st0:(1-fCos)*ecx[0]*ecx[1]
; st1:(1-fCos)*ecx[1]
; st2:(1-fCos)*ecx[0]
; st3:1-fCos
; st4:ecx[2]
; st5:ecx[1]
; st6:ecx[0]
; st7:
; ~~~~~~~~~~~~
fld st(2) ; st0:(1-fCos)*ecx[0]
; st1:(1-fCos)*ecx[0]*ecx[1]
; st2:(1-fCos)*ecx[1]
; st3:(1-fCos)*ecx[0]
; st4:1-fCos
; st5:ecx[2]
; st6:ecx[1]
; st7:ecx[0]
; ~~~~~~~~~~~~
fmul st, st(5) ; st0:(1-fCos)*ecx[0]*ecx[2]
; st1:(1-fCos)*ecx[0]*ecx[1]
; st2:(1-fCos)*ecx[1]
; st3:(1-fCos)*ecx[0]
; st4:1-fCos
; st5:ecx[2]
; st6:ecx[1]
; st7:ecx[0]
; ~~~~~~~~~~~~
fstp [ebp+var_8] ; var_8=(1-fCos)*ecx[0]*ecx[2]
; st0:(1-fCos)*ecx[0]*ecx[1]
; st1:(1-fCos)*ecx[1]
; st2:(1-fCos)*ecx[0]
; st3:1-fCos
; st4:ecx[2]
; st5:ecx[1]
; st6:ecx[0]
; st7:
; ~~~~~~~~~~~~
fld st(1) ; st0:(1-fCos)*ecx[1]
; st1:(1-fCos)*ecx[0]*ecx[1]
; st2:(1-fCos)*ecx[1]
; st3:(1-fCos)*ecx[0]
; st4:1-fCos
; st5:ecx[2]
; st6:ecx[1]
; st7:ecx[0]
; ~~~~~~~~~~~~
fmul st, st(5) ; st0:(1-fCos)*ecx[1]*ecx[2]
; st1:(1-fCos)*ecx[0]*ecx[1]
; st2:(1-fCos)*ecx[1]
; st3:(1-fCos)*ecx[0]
; st4:1-fCos
; st5:ecx[2]
; st6:ecx[1]
; st7:ecx[0]
; ~~~~~~~~~~~~
fstp [ebp+var_20] ; var_20 = (1-fCos)*ecx[1]*ecx[2]
; st0:(1-fCos)*ecx[0]*ecx[1]
; st1:(1-fCos)*ecx[1]
; st2:(1-fCos)*ecx[0]
; st3:1-fCos
; st4:ecx[2]
; st5:ecx[1]
; st6:ecx[0]
; st7:
; ~~~~~~~~~~~~
fld st(6) ; st0:ecx[0]
; st1:(1-fCos)*ecx[0]*ecx[1]
; st2:(1-fCos)*ecx[1]
; st3:(1-fCos)*ecx[0]
; st4:1-fCos
; st5:ecx[2]
; st6:ecx[1]
; st7:ecx[0]
; ~~~~~~~~~~~~
fmul [ebp+fSin] ; st0:ecx[0]*fSin
; st1:(1-fCos)*ecx[0]*ecx[1]
; st2:(1-fCos)*ecx[1]
; st3:(1-fCos)*ecx[0]
; st4:1-fCos
; st5:ecx[2]
; st6:ecx[1]
; st7:ecx[0]
; ~~~~~~~~~~~~
fstp [ebp+var_18] ; var_18 = ecx[0]*fsin
; st0:(1-fCos)*ecx[0]*ecx[1]
; st1:(1-fCos)*ecx[1]
; st2:(1-fCos)*ecx[0]
; st3:1-fCos
; st4:ecx[2]
; st5:ecx[1]
; st6:ecx[0]
; st7:
; ~~~~~~~~~~~~
fld st(5) ; st0:ecx[1]
; st1:(1-fCos)*ecx[0]*ecx[1]
; st2:(1-fCos)*ecx[1]
; st3:(1-fCos)*ecx[0]
; st4:1-fCos
; st5:ecx[2]
; st6:ecx[1]
; st7:ecx[0]
; ~~~~~~~~~~~~
fmul [ebp+fSin] ; st0:ecx[1]*fSin
; st1:(1-fCos)*ecx[0]*ecx[1]
; st2:(1-fCos)*ecx[1]
; st3:(1-fCos)*ecx[0]
; st4:1-fCos
; st5:ecx[2]
; st6:ecx[1]
; st7:ecx[0]
; ~~~~~~~~~~~~
fstp [ebp+var_10] ; var_10 = ecx[1]*fsin
; st0:(1-fCos)*ecx[0]*ecx[1]
; st1:(1-fCos)*ecx[1]
; st2:(1-fCos)*ecx[0]
; st3:1-fCos
; st4:ecx[2]
; st5:ecx[1]
; st6:ecx[0]
; st7:
; ~~~~~~~~~~~~
fld st(4) ; st0:ecx[2]
; st1:(1-fCos)*ecx[0]*ecx[1]
; st2:(1-fCos)*ecx[1]
; st3:(1-fCos)*ecx[0]
; st4:1-fCos
; st5:ecx[2]
; st6:ecx[1]
; st7:ecx[0]
; ~~~~~~~~~~~~
fmul [ebp+fSin] ; st0:ecx[2]*fSin
; st1:(1-fCos)*ecx[0]*ecx[1]
; st2:(1-fCos)*ecx[1]
; st3:(1-fCos)*ecx[0]
; st4:1-fCos
; st5:ecx[2]
; st6:ecx[1]
; st7:ecx[0]
; ~~~~~~~~~~~~
fstp [ebp+fSin] ; fSin = ecx[2]*fSin
; st0:(1-fCos)*ecx[0]*ecx[1]
; st1:(1-fCos)*ecx[1]
; st2:(1-fCos)*ecx[0]
; st3:1-fCos
; st4:ecx[2]
; st5:ecx[1]
; st6:ecx[0]
; st7:
; ~~~~~~~~~~~~
fxch st(2) ; st0:(1-fCos)*ecx[0]
; st1:(1-fCos)*ecx[1]
; st2:(1-fCos)*ecx[0]*ecx[1]
; st3:1-fCos
; st4:ecx[2]
; st5:ecx[1]
; st6:ecx[0]
; st7:
; ~~~~~~~~~~~~
fmul st, st(6) ; st0:(1-fCos)*ecx[0]*ecx[0]
; st1:(1-fCos)*ecx[1]
; st2:(1-fCos)*ecx[0]*ecx[1]
; st3:1-fCos
; st4:ecx[2]
; st5:ecx[1]
; st6:ecx[0]
; st7:
; ~~~~~~~~~~~~
fadd [ebp+fCos] ; st0:(1-fCos)*ecx[0]*ecx[0]+fCos
; st1:(1-fCos)*ecx[1]
; st2:(1-fCos)*ecx[0]*ecx[1]
; st3:1-fCos
; st4:ecx[2]
; st5:ecx[1]
; st6:ecx[0]
; st7:
; ~~~~~~~~~~~~
fstp qword ptr [eax] ; eax[0] = (1-fCos)*ecx[0]*ecx[0]+fCos
; st0:(1-fCos)*ecx[1]
; st1:(1-fCos)*ecx[0]*ecx[1]
; st2:1-fCos
; st3:ecx[2]
; st4:ecx[1]
; st5:ecx[0]
; st6:
; st7:
; ~~~~~~~~~~~~
fld [ebp+fSin] ; st0:ecx[2]*fSin
; st1:(1-fCos)*ecx[1]
; st2:(1-fCos)*ecx[0]*ecx[1]
; st3:1-fCos
; st4:ecx[2]
; st5:ecx[1]
; st6:ecx[0]
; st7:
; ~~~~~~~~~~~~
fsubr st, st(2) ; st0:(1-fCos)*ecx[0]*ecx[1] - ecx[2]*fSin
; st1:(1-fCos)*ecx[1]
; st2:(1-fCos)*ecx[0]*ecx[1]
; st3:1-fCos
; st4:ecx[2]
; st5:ecx[1]
; st6:ecx[0]
; st7:
; ~~~~~~~~~~~~
fstp qword ptr [eax+8] ; eax[1] = (1-fCos)*ecx[0]*ecx[1] - ecx[2]*fSin
; st0:(1-fCos)*ecx[1]
; st1:(1-fCos)*ecx[0]*ecx[1]
; st2:1-fCos
; st3:ecx[2]
; st4:ecx[1]
; st5:ecx[0]
; st6:
; st7:
; ~~~~~~~~~~~~
fld [ebp+var_10] ; st0:ecx[1]*fsin
; st1:(1-fCos)*ecx[1]
; st2:(1-fCos)*ecx[0]*ecx[1]
; st3:1-fCos
; st4:ecx[2]
; st5:ecx[1]
; st6:ecx[0]
; st7:
; ~~~~~~~~~~~~
fadd [ebp+var_8] ; st0:ecx[1]*fsin+(1-fCos)*ecx[0]*ecx[2]
; st1:(1-fCos)*ecx[1]
; st2:(1-fCos)*ecx[0]*ecx[1]
; st3:1-fCos
; st4:ecx[2]
; st5:ecx[1]
; st6:ecx[0]
; st7:
; ~~~~~~~~~~~~
fstp qword ptr [eax+10h] ; eax[2] = (1-fCos)*ecx[0]*ecx[2] + ecx[1]*fsin
; st0:(1-fCos)*ecx[1]
; st1:(1-fCos)*ecx[0]*ecx[1]
; st2:1-fCos
; st3:ecx[2]
; st4:ecx[1]
; st5:ecx[0]
; st6:
; st7:
; ~~~~~~~~~~~~
fld [ebp+fSin] ; st0:ecx[2]*fSin
; st1:(1-fCos)*ecx[1]
; st2:(1-fCos)*ecx[0]*ecx[1]
; st3:1-fCos
; st4:ecx[2]
; st5:ecx[1]
; st6:ecx[0]
; st7:
; ~~~~~~~~~~~~
fadd st, st(2) ; st0:ecx[2]*fSin + (1-fCos)*ecx[0]*ecx[1]
; st1:(1-fCos)*ecx[1]
; st2:(1-fCos)*ecx[0]*ecx[1]
; st3:1-fCos
; st4:ecx[2]
; st5:ecx[1]
; st6:ecx[0]
; st7:
; ~~~~~~~~~~~~
fstp qword ptr [eax+18h] ; eax[3] = (1-fCos)*ecx[0]*ecx[1] + ecx[2]*fSin
; st0:(1-fCos)*ecx[1]
; st1:(1-fCos)*ecx[0]*ecx[1]
; st2:1-fCos
; st3:ecx[2]
; st4:ecx[1]
; st5:ecx[0]
; st6:
; st7:
; ~~~~~~~~~~~~
fstp st(1) ; st0:(1-fCos)*ecx[1]
; st1:1-fCos
; st2:ecx[2]
; st3:ecx[1]
; st4:ecx[0]
; st5:
; st6:
; st7:
; ~~~~~~~~~~~~
fmul st, st(3) ; st0:(1-fCos)*ecx[1]*ecx[1]
; st1:1-fCos
; st2:ecx[2]
; st3:ecx[1]
; st4:ecx[0]
; st5:
; st6:
; st7:
; ~~~~~~~~~~~~
fadd [ebp+fCos] ; st0:(1-fCos)*ecx[1]*ecx[1]+fCos
; st1:1-fCos
; st2:ecx[2]
; st3:ecx[1]
; st4:ecx[0]
; st5:
; st6:
; st7:
; ~~~~~~~~~~~~
fstp qword ptr [eax+20h] ; eax[4] = (1-fCos)*ecx[1]*ecx[1] + fCos
; st0:1-fCos
; st1:ecx[2]
; st2:ecx[1]
; st3:ecx[0]
; st4:
; st5:
; st6:
; st7:
; ~~~~~~~~~~~~
fld [ebp+var_20] ; st0:(1-fCos)*ecx[1]*ecx[2]
; st1:1-fCos
; st2:ecx[2]
; st3:ecx[1]
; st4:ecx[0]
; st5:
; st6:
; st7:
; ~~~~~~~~~~~~
fsub [ebp+var_18] ; st0:(1-fCos)*ecx[1]*ecx[2]-ecx[0]*fsin
; st1:1-fCos
; st2:ecx[2]
; st3:ecx[1]
; st4:ecx[0]
; st5:
; st6:
; st7:
; ~~~~~~~~~~~~
fstp qword ptr [eax+28h] ; eax[5] = (1-fCos)*ecx[1]*ecx[2] - ecx[0]*fsin
; st0:1-fCos
; st1:ecx[2]
; st2:ecx[1]
; st3:ecx[0]
; st4:
; st5:
; st6:
; st7:
; ~~~~~~~~~~~~
fld [ebp+var_8] ; st0:(1-fCos)*ecx[0]*ecx[2]
; st1:1-fCos
; st2:ecx[2]
; st3:ecx[1]
; st4:ecx[0]
; st5:
; st6:
; st7:
; ~~~~~~~~~~~~
fsub [ebp+var_10] ; st0:(1-fCos)*ecx[0]*ecx[2]-ecx[1]*fsin
; st1:1-fCos
; st2:ecx[2]
; st3:ecx[1]
; st4:ecx[0]
; st5:
; st6:
; st7:
; ~~~~~~~~~~~~
fstp qword ptr [eax+30h] ; eax[6] = (1-fCos)*ecx[0]*ecx[2] - ecx[1]*fsin
; st0:1-fCos
; st1:ecx[2]
; st2:ecx[1]
; st3:ecx[0]
; st4:
; st5:
; st6:
; st7:
; ~~~~~~~~~~~~
fld [ebp+var_18] ; st0:ecx[0]*fsin
; st1:1-fCos
; st2:ecx[2]
; st3:ecx[1]
; st4:ecx[0]
; st5:
; st6:
; st7:
; ~~~~~~~~~~~~
fadd [ebp+var_20] ; st0:ecx[0]*fsin+(1-fCos)*ecx[1]*ecx[2]
; st1:1-fCos
; st2:ecx[2]
; st3:ecx[1]
; st4:ecx[0]
; st5:
; st6:
; st7:
; ~~~~~~~~~~~~
fstp qword ptr [eax+38h] ; eax[7] = (1-fCos)*ecx[1]*ecx[2] + ecx[0]*fsin
; st0:1-fCos
; st1:ecx[2]
; st2:ecx[1]
; st3:ecx[0]
; st4:
; st5:
; st6:
; st7:
; ~~~~~~~~~~~~
fmul st, st(1)
fmul st, st(1) ; st0:(1-fCos)*ecx[2]*ecx[2]
; st1:ecx[2]
; st2:ecx[1]
; st3:ecx[0]
; st4:
; st5:
; st6:
; st7:
; ~~~~~~~~~~~~
fadd [ebp+fCos] ; st0:(1-fCos)*ecx[2]*ecx[2]+fCos
; st1:ecx[2]
; st2:ecx[1]
; st3:ecx[0]
; st4:
; st5:
; st6:
; st7:
; ~~~~~~~~~~~~
fstp qword ptr [eax+40h] ; eax[8] = (1-fCos)*ecx[2]*ecx[2] + fCos
; st1:ecx[2]
; st2:ecx[1]
; st3:ecx[0]
; st4:
; st5:
; st6:
; st7:
; ~~~~~~~~~~~~
mov ecx, ds:__imp_?MACH__checking_level@@3HA ; int MACH__checking_level
cmp dword ptr [ecx], 0
fstp st
fstp st
fstp st
jle short loc_201CB490
push eax ; struct MTX3_s *
call ?MTX3_is_ortho_normal@@YAEPBUMTX3_s@@@Z ; MTX3_is_ortho_normal(MTX3_s const *)
add esp, 4
test al, al
jnz short loc_201CB490
push offset aMtx3_is_ortho_ ; "MTX3_is_ortho_normal (r)"
push 1A9h
push offset aDUgnx30Sand_18 ; "D://ugnx30//sandbox//src//ugmath//no//ind//mtx"...
call ds:__imp_?ERROR_assertion_failed@@YAXPBDH0@Z ; ERROR_assertion_failed(char const *,int,char const *)
add esp, 0Ch
loc_201CB490: ; CODE XREF: sub_201CB3C0+A9j
; sub_201CB3C0+B6j
mov esp, ebp
pop ebp
retn
sub_201CB3C0 endp
他是用 eax,ecx 这两个寄存器传参的
; (eax->mtx, ecx->unit_vec, fCos, fSin)
Eax 传的是矩阵的指针 ,ecx 传的是矢量的指针 , 后两个参数是由角度算出的 sin 和 cos 值
最后整理成公式 :
eax[0] = (1-fCos)*ecx[0]*ecx[0] + fCos
eax[1] = (1-fCos)*ecx[0]*ecx[1] - ecx[2]*fSin
eax[2] = (1-fCos)*ecx[0]*ecx[2] + ecx[1]*fsin
eax[3] = (1-fCos)*ecx[0]*ecx[1] + ecx[2]*fSin
eax[4] = (1-fCos)*ecx[1]*ecx[1] + fCos
eax[5] = (1-fCos)*ecx[1]*ecx[2] - ecx[0]*fsin
eax[6] = (1-fCos)*ecx[0]*ecx[2] - ecx[1]*fsin
eax[7] = (1-fCos)*ecx[1]*ecx[2] + ecx[0]*fsin
eax[8] = (1-fCos)*ecx[2]*ecx[2] + fCos
这个就是转换的 3*3 矩阵公式
我用的是 NX3.0, 每次只要旋转图形时 , 他都会到这里来走一堂的 , 呵呵 !
这里是我在网上找到的一篇文章
3D 空间中的旋转可用旋转矩阵、欧拉角或四元数等形式来表示,他们不过都是数学工具,其中在绕任意向量的旋转方面,旋转矩阵和四元数两种工具用的较多,欧拉角由于存在万向节死锁等问题,使用存在限制。
(本文假设坐标系为左手坐标系中,旋转方向为顺时针。)
所求问题:
给定任意单位轴 q(q1,q2,q3)( 向量 ), 求向量 p(x,y,z)( 或点 p) 饶 q 旋转 theta 角度的变换后的新向量 p'( 或点 p') :
1. 用四元数工具:
-------------------------------------------------------------------------
结论:构造四元数变换 p'= q*p*q-1 ,( p,q 是由向量 p,q 扩展成的四元数)。那么, p' 转换至对应的向量 ( 或点 ) 就是变换后的新向量 p'( 或点 p') 。
其中, p',q,p,q-1 均为四元数。 q 由向量 q 扩展 , 为 q=(cos(theta/2),sin(theta/2)*q) , p 由向量 p 扩展 , 为 p=(0,x,y,z),q-1 为 q 的逆,因为 q 为单位四元数,所以 q-1=q*=(cos(theta/2),-sin(theta/2)*q) 。
-------------------------------------------------------------------------
(这个结论的证明过程可以在网上找到。这里略去。)
下面看其时间复杂度:
首先有个三角函数的计算时间,这个可以预先计算好,花费时间不计。考虑 n 个四元数相乘需进行 4*4*(n-1)=16*(n-1) 次乘法, 15*(n-1) 次加法,因为加法化费时间较少,这里仅考虑乘法。这里涉及到三个四元数的乘法,设一次乘法的时间为 T, 故花费 16*2=32T
2. 旋转矩阵工具:
-------------------------------------------------------------------------
结论:构造旋转矩阵变换 Trot, 则变换后的新向量 p'( 或点 p') 为 p'= p*Trot
其中, p' ( x',y',z',1 ) ,p(x,y,z,1) 为向量 p' , p 的 4D 齐次坐标表示, Trot =
|t*q1*q1 + c, t*q1*q2 + s*q3, t*q1*q3 - s*q2, 0|
|t*q1*q2 - s*q3, t*q2*q2 + c, t*q2*q3 + s*q1, 0|
|t*q1*q3 + s*q2, t*q2*q3 - s*q1, t*q3*q3 + c, 0|
|0, 0, 0, 1|
c=cos(theta), s=sin(theta),t=1-c.
-------------------------------------------------------------------------
(这个结论的证明过程可以在网上找到。这里略去。)
下面看其时间复杂度:
三角函数的计算时间不计。矩阵本身的元素乘法主要是计算 t*x 和 s*x 之类,需进行 12+3=15 次乘法。两个矩阵相乘的需进行 n*n*n 次乘法 , 这里 n=4 ,所以花费 4*4*4=64 次乘法时间 , 但这里有个注意的地方就是旋转矩阵的第 4 维无须考虑,即可简化为 3X3 的矩阵。故花费 3*3*3=27 次乘法时间,总共的时间为 15+27=42 次乘法时间。 cost=42T.
比较来看,还是使用四元数的效率要高出一些,这在要变换的点的数目越大时,体现的越明显。实际上,有很多 3D 引擎为了利用四元数运算的高效率性,一般先将矩阵转换成四元数后进行运算再转回为矩阵后,再传给 DirectX 或 OpenGL 库函数。
关于四元数和矩阵在向量(方向)之间的进行插值的效率比较,未完待续。
本文来自 CSDN 博客,转载请标明出处: http://blog.csdn.net/xueyong1203/archive/2007/02/14/1510022.aspx
整理成公式
f9[0] = t*q1*q1 + c;
f9[1] = t*q1*q2 + s*q3;
f9[2] = t*q1*q3 - s*q2;
f9[3] = t*q1*q2 - s*q3;
f9[4] = t*q2*q2 + c;
f9[5] = t*q2*q3 + s*q1;
f9[6] = t*q1*q3 + s*q2;
f9[7] = t*q2*q3 - s*q1;
f9[8] = t*q3*q3 + c;
eax[0] = (1-fCos)*ecx[0]*ecx[0] + fCos
eax[1] = (1-fCos)*ecx[0]*ecx[1] - ecx[2]*fSin
eax[2] = (1-fCos)*ecx[0]*ecx[2] + ecx[1]*fsin
eax[3] = (1-fCos)*ecx[0]*ecx[1] + ecx[2]*fSin
eax[4] = (1-fCos)*ecx[1]*ecx[1] + fCos
eax[5] = (1-fCos)*ecx[1]*ecx[2] - ecx[0]*fsin
eax[6] = (1-fCos)*ecx[0]*ecx[2] - ecx[1]*fsin
eax[7] = (1-fCos)*ecx[1]*ecx[2] + ecx[0]*fsin
eax[8] = (1-fCos)*ecx[2]*ecx[2] + fCos
发现有的地方符号正好相反 , 后来经研究发现他假设的是 坐标系为左手坐标系中,旋转方向为顺时针
而我们的 NX 是右手坐标系 , 所以计算矩阵的算法还是有区别的
2010.05.10 by xusir98
最后
以上就是现代乐曲为你收集整理的Simens NX (原UG)内部代码逆向分析 / Inner code Reverse analysis of NX software的全部内容,希望文章能够帮你解决Simens NX (原UG)内部代码逆向分析 / Inner code Reverse analysis of NX software所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复