《Reverse Engineering for Beginners》 - 第1章 代码模式 - 笔记(1.14)

本文详细分析了x86、ARM、ARM64和MIPS架构下,switch/case/default在不同编译器优化情况下的实现方式,包括case数量较少、大量cases和不连续case的处理,以及fall-through的情况。通过实例展示了编译器如何生成跳转表和使用条件跳转指令来实现switch语句。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1.14. switch()/case/default

1.14.1. case数量较少

x86

未优化MSVC

case数量较少时,相当于数个if/else语句结合。光看汇编代码很难判断源代码是什么。

优化后的MSVC

一些优化很有趣:把a的值放在EAX中,用它减去0,用来检查a是否为0。如果ZF设置了(减法结果为0),则JE触发。接下来会分别减1、减2,即分别与1,2比较。

另一点是,调用printf()不是用CALL,而是用JMP。字符串指针放在a变量(某个内存地址),这段代码只是手动设置栈内容然后跳转。实际上是为了速度而优化。

OllyDbg

可以识别case语句。

ARM:优化Keil(ARM模式)

也是按if实现的。出现了比较多的ADRcc指令,在特定条件下加载字符串地址到R0,下一条Bxx跳转到某个位置,进行函数调用。

ARM:优化Keil(Thumb模式)

没有后缀形式,所以与x86差不多。

ARM64:未优化GCC

用w0保存输入而不是x0,因为是int类型。
用ADRP/ADD将字符串指针参数传给puts()。

ARM64:优化的GCC

用CBZ代替了复杂的指令,如果w0是0就跳转。直接跳转到puts()。

MIPS

jr $t9 跳转到puts()
LW指令后常有nop,因为load delay slot。

结论:

少量case的switch()与if/else基本没有区别。

1.14.2. 大量cases

如果case较多,则用大量JE/JNE指令是不合适的。

下面给出了一个5个case的例子。

x86

非优化的MSVC

如果a大于4,直接跳到$LN1@f(错误信息)。

如果a小于等于4,把a乘以4,再与LN11@f

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值