逆向时碰到一段指令,出现了sse指令,是gcc优化成sse指令的结果。编译程序时,可以使用 -mno-sse 选项禁止使用sse编译优化。因没有源码,碰到sse指令,试试看了。几个指令在一起,分开来分析。
347d: 66 0f ef c0 pxor %xmm0,%xmm0 // xmm0=0.0
3481: f2 48 0f 2a c0 cvtsi2sd %rax,%xmm0 // xmm0=rax=45.0
3486: f2 0f 5e 44 24 48 divsd 0x48(%rsp),%xmm0 // xmm0=xmm0/(rsp+0x48)=45.0/100.0=0.45
348c: f2 0f 5c c8 subsd %xmm0,%xmm1 // xmm1=xmm1-xmm0=29524.169999999998-0.45=29523.719999999998
3490: 66 0f ef db pxor %xmm3,%xmm3 // xmm3=0.0
3494: 48 8d 45 01 lea 0x1(%rbp),%rax // rax=strchr_ret+1
3498: 83 3d a5 5f 00 00 00 cmpl $0x0,0x5fa5(%rip) */ # 9444 <stderr@@GLIBC_2.2.5+0x24> // 9444=0
if (gvar_9444 == 0) {
349f: 48 89 44 24 08 mov %rax,0x8(%rsp) // (rsp+0x8)=rax=strchr_ret+1
34a4: f2 0f 5f d9 maxsd %xmm1,%xmm3 // xmm3=xmm1=29523.719999999998
34a8: f2 0f 11 5c 24 48 movsd %xmm3,0x48(%rsp) // (rsp+0x48)=29523.719999999998
34ae: 0f 84 26 02 00 00 je 36da <__sprintf_chk@plt+0xf6a> // jump
// je 36da
}
3486: f2 0f 5e 44 24 48 divsd 0x48(%rsp),%xmm0
divsd 指令:
Divide scalar double precision floating-point values。
目的寄存器低64位1个双精度浮点数除以源存储器低64位1个双精度浮点数,结果送入目的寄存器的低64位,高64位不变,内存变量不必对齐内存16字节。
gdb 调测:
=> 0x000055555555747d: 66 0f ef c0 pxor %xmm0,%xmm0
(gdb) p/f $xmm0
$1 = {v4_float = {-2.33146828e-17, 7.05728912, 0, 0}, v2_double = {36522.519999999997, 0}, v16_int8 = {61, 10,
-41, -93, 80, -43, -31, 64, 0, 0, 0, 0, 0, 0, 0, 0}, v8_int16 = {2621, -23593, -10928, 16609, 0, 0, 0, 0},
v4_int32 = {-2.33146828e-17, 7.05728912, 0, 0}, v2_int64 = {36522.519999999997, 0},
uint128 = 1.70422279711280534059e-4932}
(gdb) n
0x0000555555557481 in ?? ()
=> 0x0000555555557481: f2 48 0f 2a c0 cvtsi2sd %rax,%xmm0
(gdb) p/f $xmm0
$2 = {v4_float = {0, 0, 0, 0}, v2_double = {0, 0}, v16_int8 = {0 <repeats 16 times>}, v8_int16 = {0, 0, 0, 0,
0, 0, 0, 0}, v4_int32 = {0, 0, 0, 0}, v2_int64 = {0, 0}, uint128 = 0}
(gdb) p/x $rax
$3 = 0x2d
(gdb) n
0x0000555555557486 in ?? ()
=> 0x0000555555557486: f2 0f 5e 44 24 48 divsd 0x48(%rsp),%xmm0
(gdb) p/f $xmm0
$4 = {v4_float = {0, 3.1015625, 0, 0}, v2_double = {45, 0}, v16_int8 = {0, 0, 0, 0, 0, -128, 70, 64, 0, 0, 0,
0, 0, 0, 0, 0}, v8_int16 = {0, 0, -32768, 16454, 0, 0, 0, 0}, v4_int32 = {0, 3.1015625, 0, 0}, v2_int64 = {
45, 0}, uint128 = 1.68828510035211006466e-4932}
(gdb) x/fg $rsp+0x48
0x7fffffff9ad8: 100
(gdb) n
0x000055555555748c in ?? ()
=> 0x000055555555748c: f2 0f 5c c8 subsd %xmm0,%xmm1
(gdb) p/f $xmm0
$5 = {v4_float = {-107374184, 1.7249999, 0, 0}, v2_double = {0.45000000000000001, 0}, v16_int8 = {-51, -52,
-52, -52, -52, -52, -36, 63, 0, 0, 0, 0, 0, 0, 0, 0}, v8_int16 = {-13107, -13108, -13108, 16348, 0, 0, 0,
0}, v4_int32 = {-107374184, 1.7249999, 0, 0}, v2_int64 = {0.45000000000000001, 0},
uint128 = 1.67743993732028180901e-4932}
(gdb) p/f $xmm1
$6 = {v4_float = {-2.33146828e-17, 7.05728912, 0, 0}, v2_double = {36522.519999999997, 0}, v16_int8 = {61, 10,
-41, -93, 80, -43, -31, 64, 0, 0, 0, 0, 0, 0, 0, 0}, v8_int16 = {2621, -23593, -10928, 16609, 0, 0, 0, 0},
v4_int32 = {-2.33146828e-17, 7.05728912, 0, 0}, v2_int64 = {36522.519999999997, 0},
uint128 = 1.70422279711280534059e-4932}
(gdb) n
0x0000555555557490 in ?? ()
=> 0x0000555555557490: 66 0f ef db pxor %xmm3,%xmm3
(gdb) p/f $xmm0
$7 = {v4_float = {-107374184, 1.7249999, 0, 0}, v2_double = {0.45000000000000001, 0}, v16_int8 = {-51, -52,
-52, -52, -52, -52, -36, 63, 0, 0, 0, 0, 0, 0, 0, 0}, v8_int16 = {-13107, -13108, -13108, 16348, 0, 0, 0,
0}, v4_int32 = {-107374184, 1.7249999, 0, 0}, v2_int64 = {0.45000000000000001, 0},
uint128 = 1.67743993732028180901e-4932}
(gdb) p/f $xmm1
$8 = {v4_float = {0.0587499999, 7.05728245, 0, 0}, v2_double = {36522.07, 0}, v16_int8 = {-41, -93, 112, 61,
66, -43, -31, 64, 0, 0, 0, 0, 0, 0, 0, 0}, v8_int16 = {-23593, 15728, -10942, 16609, 0, 0, 0, 0},
v4_int32 = {0.0587499999, 7.05728245, 0, 0}, v2_int64 = {36522.07, 0}, uint128 = 1.7042227745681469421e-4932}
(gdb) n
0x0000555555557494 in ?? ()
=> 0x0000555555557494: 48 8d 45 01 lea 0x1(%rbp),%rax
(gdb) p/f $xmm3
$9 = {v4_float = {0, 0, 0, 0}, v2_double = {0, 0}, v16_int8 = {0 <repeats 16 times>}, v8_int16 = {0, 0, 0, 0,
0, 0, 0, 0}, v4_int32 = {0, 0, 0, 0}, v2_int64 = {0, 0}, uint128 = 0}
(gdb) n
0x0000555555557498 in ?? ()
=> 0x0000555555557498: 83 3d a5 5f 00 00 00 cmpl $0x0,0x5fa5(%rip) # 0x55555555d444
(gdb)
0x000055555555749f in ?? ()
=> 0x000055555555749f: 48 89 44 24 08 mov %rax,0x8(%rsp)
(gdb)
0x00005555555574a4 in ?? ()
=> 0x00005555555574a4: f2 0f 5f d9 maxsd %xmm1,%xmm3
(gdb) p/f $xmm1
$10 = {v4_float = {0.0587499999, 7.05728245, 0, 0}, v2_double = {36522.07, 0}, v16_int8 = {-41, -93, 112, 61,
66, -43, -31, 64, 0, 0, 0, 0, 0, 0, 0, 0}, v8_int16 = {-23593, 15728, -10942, 16609, 0, 0, 0, 0},
v4_int32 = {0.0587499999, 7.05728245, 0, 0}, v2_int64 = {36522.07, 0}, uint128 = 1.7042227745681469421e-4932}
(gdb) p/f $xmm3
$11 = {v4_float = {0, 0, 0, 0}, v2_double = {0, 0}, v16_int8 = {0 <repeats 16 times>}, v8_int16 = {0, 0, 0, 0,
0, 0, 0, 0}, v4_int32 = {0, 0, 0, 0}, v2_int64 = {0, 0}, uint128 = 0}
(gdb) n
0x00005555555574a8 in ?? ()
=> 0x00005555555574a8: f2 0f 11 5c 24 48 movsd %xmm3,0x48(%rsp)
(gdb) p/f $xmm3
$12 = {v4_float = {0.0587499999, 7.05728245, 0, 0}, v2_double = {36522.07, 0}, v16_int8 = {-41, -93, 112, 61,
66, -43, -31, 64, 0, 0, 0, 0, 0, 0, 0, 0}, v8_int16 = {-23593, 15728, -10942, 16609, 0, 0, 0, 0},
v4_int32 = {0.0587499999, 7.05728245, 0, 0}, v2_int64 = {36522.07, 0}, uint128 = 1.7042227745681469421e-4932}
(gdb) n
0x00005555555574ae in ?? ()
=> 0x00005555555574ae: 0f 84 26 02 00 00 je 0x5555555576da
(gdb) x/fg $rsp+0x48
0x7fffffff9ad8: 36522.07
结论:
divsd 除法指令,重点关注一下xmm寄存器中的 v2_double 字段,先除后减再把值传到内存,跟着稍微验算一下就能弄清指令的特性。
但还没有搞清楚这段sse指令的目的为何。