Win32反汇编(七)浮点指令(FLD / FILD / FSTP)与位移指令的逆向分析

前言

作者:浪子花梦,一个有趣的程序员 ~
此系列文章都是一些基础的文章,每篇文章都通过几个小例子快速的了解 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)逻辑位移指令:

  1. SHR 逻辑右移指令:右移一位相当于 / 2,用 0 补位
  2. SHL 逻辑左移指令:左移一位相当于 * 2,用 0 补位(可能会溢出)

2)算术位移指令:

  1. SAR 算术右移指令:SAR 与 SHR差不多,只不过用 符号位来补位
  2. SAL 算术左移指令:与 SHL 一样

3)循环位移指令:

  1. ROL 循环左移
  2. 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, 16
		ror n, 16
	}
	 
	printf("end!\n");

	return 0;
}

使用OD 调试如下所示:
在这里插入图片描述

演示效果如下所示,使用 dd命令查看数据:

在这里插入图片描述

我们发现最后的结果又回来了,出来混的,最终是要还的 . . .

.
.


  • 2
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值