c++中if语句的反汇编及优化

C++ if语句反汇编

只有一个if的情况

首先我们通过观察debug选项下的汇编代码,对if语句有一个大致的了解。程序的源代码非常简单,如下:

cpp 复制代码
#include <stdio.h>

int main(int argc, char* argv[])
{
	if (argc == 0)
		printf("argc == 0");

	return 0;
}

我们先在if语句处下断点,直接在vs2022中进行调试

从图中我们可以看到,反汇编使用的判断与0相比较,并进行了jne不等于则跳转指令,跳转的地址正是整个if逻辑的结束地址。如果跳转条件不成立的话,则执行的是满足源代码中if语句块的代码。

接下来我们修改一下源代码,如下:

cpp 复制代码
#include <stdio.h>

int main(int argc, char* argv[])
{
	if (argc > 0)
		printf("argc > 0");

	return 0;
}

同样是在debug编译选项中,进行调试,同样在if语句处下断点

这里使用了jle小于等于则跳转指令,跳转的目的地是整个if语句的结束地址。如果跳转条件不成立的话,则执行的是满足源代码中if语句块的代码。

我们源代码中使用的是大于比较符,而汇编代码中使用的是小于等于跳转指令。似乎汇编中的判断条件总是和源代码中相反的,我们先不着急下结论,在多看几种情况。

if和else

我们修改一下先前的源代码,如下:

cpp 复制代码
#include <stdio.h>

int main(int argc, char* argv[])
{
	if (argc == 0)
		printf("argc == 0");
	else
		printf("argc != 0");

	return 0;
}

使用Debug编译选项。同样在if处下断点,反汇编代码如下:

同样的,if语句的反汇编代码中进行的是和源代码中相反的判断,跳转的地址是else语句块的起始地址。如果跳转条件不成立,则会执行if语句块中的代码,并且我们可以看到,为了跳过紧挨着if语句块反汇编代码末尾的else反汇编代码块,在if反汇编代码块的末尾处,使用了无条件跳转指令跳转到整个if else逻辑的结束地址处。

我们知道,if与else语句和条件表达式语句(三目运算符)的功能是相同的,我之前写过一篇博客,里面讨论了对条件表达式的反汇编和优化,既然两者的功能是相同的,那么它们在反汇编的优化上是否有相似之处呢?答案是有的。读者可以参考那篇文章,自己构造测试代码并反汇编,看看其中的优化方案。笔者实验后发现,if...else语句和条件表达式使用的是同一套优化策略。

if多分支语句

先给出我们的测试代码:

cpp 复制代码
#include <stdio.h>

int main(int argc, char* argv[])
{
	if (argc > 0) {
		printf("argc > 0");
	}
	else if (argc == 0) {
		printf("argc == 0");
	}
	else {
		printf("argc <= 0");
	}
	return 0;
}

在Release下编译并反汇编,得到的汇编代码如下所示:

在反汇编视图中我们可以看到,先是使用了test指令对argc进行按位与运算,判断argc是否为0,并设置了SF(为1时表示运算结果为负数),而jle指令执行的是小于等于则跳转,要执行jle指令会先检查SF标志位(其实还需要检查OF溢出标志位,但test指令并不影响该标志位,始终将其置0),当SF标志位为1时,执行jle指令。所以test和jle指令的结合,用于判断一个数是否小于等于0,这与源代码中的>0相对应。如果跳转不执行,说明符合>0的条件,接下来就执行第一个if语句块中的代码,并直接ret,而不是跳转到整个多分枝if的结束处。

有趣的是对于后两个语句块的优化,它们使用了条件运算符的优化方案(详情见该篇博客),把两个printf的参数都加载,然后使用条件传输指令选择正确的参数地址,避免了使用分支跳转代码,加快了流水线的执行。

总结

在逆向还原代码的时候,因为if语句和条件判断语句的相似之处,我们可以自行选择将其还原成对应的c代码。

相关推荐
阿昭L5 天前
I Pack You:实现基本的软件壳框架
逆向工程·pe文件·加壳
booksyhay17 天前
串口调试助手注册机制研究(一)
逆向工程·串口调试助手·uartassist
带娃的IT创业者19 天前
当不可能成为可能:我将 Mac OS X 移植到了 Nintendo Wii
逆向工程·mac os x·极客·nintendo wii·操作系统移植·powerpc·硬件破解
三维频道22 天前
柔性材料3D数字化:蓝光扫描在内衣胸垫设计与质检中的应用
人工智能·3d·逆向工程·蓝光3d扫描仪·服装数字化·内衣设计·柔性材料检测
带娃的IT创业者24 天前
逆向工程与数字考古:以3万美元收购Friendster为例的技术重构实战
重构·数据清洗·逆向工程·数字考古·架构重构·friendster·技术迁移
曼岛_1 个月前
[逆向工程]160个CrackMe入门实战之aLoNg3x.2解析(七)
逆向工程
曼岛_1 个月前
[逆向工程]160个CrackMe入门实战之Andrnalin.1解析(八)
逆向工程
Pure_White_Sword1 个月前
[NSSRound#6 Team]void(V1)
网络安全·ctf·reverse·逆向工程
Pure_White_Sword1 个月前
[广东省大学生攻防大赛 2022]pyre
网络安全·ctf·reverse·逆向工程
Hello.Reader2 个月前
编译器的六大阶段详解以一行赋值语句为例
编译原理·逆向工程