前言
作者:
浪子花梦
,一个有趣的程序员 ~
此系列文章都是一些基础的文章,每篇文章都通过几个小例子快速的了解 Win32反汇编与OD的使用,在此作个笔记
如若对您有帮助,记得三连哟 ~
前文链接
Win32反汇编(一) 初步探索Win32反汇编 与 Ollydbg的简单使用
Win32反汇编(二)几种常见的指令反汇编详解:EAX、MOVSX与MOVZX、LEA、SUB、CMP与转移指令
Win32反汇编(三)深层次的了解各种转移指令:IF语句有符号与无符号跳转
Win32反汇编(四)栈的工作原理与堆栈平衡,函数方法参数的调用约定
Win32反汇编(五)C/C++中的 if-else 与 switch-case 的正向分析与反向分析
Win32反汇编(六)C/C++中的循环语句反汇编分析、置增置减反汇编分析与编译器的优化分析
文章目录
- 浮点指令
- 位移指令
浮点数在游戏中非常的重要,我们一定要好好的分析,才能找出重要的数据来 . . .
浮点指令
我们先来介绍一些常见的浮点指令
,如下所示:
1)FLD 类似于 PUSH指令(存入数据到FPU中)
2)FSTP 类似于 POP指令(从FPU中取出数据)
3)FADD 类似于 ADD指令(fadd memvar // st0 = st0 + memvar)
4)FSUB 类似于 SUB指令
5)FMUL 乘法指令
6)FDIV 除法指令
7)FILD 指令(整数放入FPU中)
8)CVTTSD2SI r32,st0/m32 —— 浮点转整数指令(运用截断处理将 st0 / m32中的一个单精度浮点值转换成 r32中的一个有符号的双字整数)
9)movss 浮点数转移到 xmm寄存器中
10)addss 浮点数作加法
11)subss 浮点数作减法
12)mulss 浮点数作乘法
13)divss 浮点数作除法
14)cvttss2si 浮点数变整数
这些指令都是针对浮点数而言的,1 ~ 8 指令现在已经不常见了,但在某些程序中还是能看见的,我们主要讲讲下面的那几种简单的浮点运算指令 . . .
下面我们就会用个小例子来反分析一下汇编指令,如下所示,cpp程序的代码:
#include <cstdio>int main() {printf("start:\n");float f = 250.666666f;f = f + 249.333334f; // 500.000000 f = f - 400.555555f; // 99.444445;f = f * 3;f = f / 5;int n = f;printf("end!\n");return 0;
}
我们使用OD来调试,如下所示:
相关的注释我已经写好了,比较简单,我们需要注意的是 xmm0这个寄存器,他用于浮点数的运算与存储,以后我们看见 xmm0~7 类似的寄存器,它一定是进行浮点运算的 . . .
.
.
位移指令
位移也是一种常见的手段,通常用于扩大一个数 2^n倍,或者缩小 2^n倍,而位移指令又分为逻辑位移、算术位移、循环位移,又分为有符号与无符号,下面就让我们一为瞧一瞧吧 . . .
首先,我们先来介绍一下几种不同位移的区别:
1)逻辑位移指令:
- SHR 逻辑右移指令:右移一位相当于 / 2,用 0 补位
- SHL 逻辑左移指令:左移一位相当于 * 2,用 0 补位(可能会溢出)
2)算术位移指令:
- SAR 算术右移指令:SAR 与 SHR差不多,只不过用 符号位来补位
- SAL 算术左移指令:与 SHL 一样
3)循环位移指令:
- ROL 循环左移
- ROR 循环右移
下面我们来介绍一下逻辑位移,也就是无符号的位移,cpp代码如下所示:
#include <cstdio>int main(){printf("start:\n");unsigned int n = 0x88442211;n >>= 8;n <<= 8;printf("end!\n");return 0;
}
使用 OD反汇编这个程序如下所示:
当执行完 shr eax, 8 这条执行时,已经将 eax的值逻辑右移 8位了,它的值应该是 00884422,高位用 0补齐,如下所示:
当执行完 shl ecx, 8 这条执行时,已经将 ecx的值逻辑左移 8位了,它的值应该是 88442200,低位用 0补齐,如下所示:
.
这就是逻辑位移,下面我们来看看算术位移吧,cpp代码如下所示:
#include <cstdio>int main(){printf("start:\n");int n = 0x88442211;n >>= 8;n <<= 8;printf("end!\n");return 0;
}
使用 OD反汇编这个程序如下所示:
我们发现算术左移居然用的不是 SAL,因为上面说过他和 SHL的功能是一样的,下面我们来看看执行完 sar这条执行的结果吧,如下图所示:
我们发现它的结果由88442211 变成了 FF884422,因为 88442211的符号位是 1,所以将用 1来补所有的位,而下面使用 shl左移的功能是一样的,结果如下所示:
下面我们再来看看循环位移是什么样子的,cpp代码如下所示:
#include <cstdio>int main(){printf("start:\n");int n = 0x88442211;__asm {rol n, 16ror n, 16}printf("end!\n");return 0;
}
使用OD 调试如下所示:
演示效果如下所示,使用 dd命令查看数据:
我们发现最后的结果又回来了,出来混的,最终是要还的 . . .
.
.