switch case 二分搜索风格

文章目录

  • 从汇编反向看 C 的 `switch`:二分搜索风格的案例分析
    • 1. 先看看源码
    • 2. 函数开头的栈和参数处理
    • 3. 第一层判断:围绕 1000 切分
    • 4. 小于 1000 的分支
    • 5. 大于 1000 的分支
    • 6. case 分支实现细节
    • 7. 从汇编“还原”成等价 C
    • 8. 为什么说这是“折半查找 / 二分搜索风格”
    • 9. 逆向工程实战经验
    • 10. 测试示例

从汇编反向看 C 的switch:二分搜索风格的案例分析

最近我在调试一段 C 代码,里面有一个switch(x),case 值很稀疏,从 10 到 20000,中间跨度很大。为了理解编译器是怎么生成汇编的,我直接打开了反汇编,想把它从汇编“还原”回 C,并且顺便观察它用的到底是跳转表还是别的策略。下面我把整个分析过程记录下来,边看汇编边总结经验。


1. 先看看源码

源码很直观:

switch(x){case10:printf("10\n");break;case50:printf("50\n");break;case100:printf("100\n");break;case200:printf("200\n");break;case500:printf("500\n");break;case1000:printf("1000\n");break;case2000:printf("2000\n");break;case5000:printf("5000\n");break;case10000:printf("10000\n");break;case20000:printf("20000\n");break;default:printf("default\n");break;}

可以看到,case 值有序但稀疏,如果编译器用传统跳转表,会浪费空间,因为跳转表跨度到 20000。猜测它可能不会用 jump table,而是用比较树 / 二分搜索风格


2. 函数开头的栈和参数处理

看汇编,函数开头是标准的栈帧建立:

00085280 push ebp 00085281 mov ebp,esp 00085283 push ecx 00085284 mov dword ptr [ebp-4],0CCCCCCCCh ... 00085296 mov eax,dword ptr [ebp+8] 00085299 mov dword ptr [ebp-4],eax
  • 参数x被保存到[ebp-4],后面所有cmp [ebp-4], imm都是在比较x

  • 这里还有几条mov ecx,8C008h / call 00081217,是编译器插的栈保护或初始化,和 switch 本身没关系。


3. 第一层判断:围绕 1000 切分

然后看到第一条关键比较:

0008529C cmp dword ptr [ebp-4],3E8h ; 1000 000852A3 jg 000852F2 ; if x > 1000 → 大区间 000852A5 cmp dword ptr [ebp-4],3E8h 000852AC je 0008538A ; if x == 1000 → case 1000

脑子里立刻画出一个思路:

  • x > 1000→ 跳去处理大数的分支

  • x == 1000→ 直接命中 case 1000

  • x < 1000→ 继续下面的小数分支

感觉就像把所有 case 分成三块,这是典型二分搜索的第一层


4. 小于 1000 的分支

继续看x < 1000的分支:

000852B2 cmp [ebp-4],64h ; 100 000852B6 jg 000852D3 ; x > 100 → 中间分支 000852B8 cmp [ebp-4],64h 000852BC je 0008535D ; x == 100 000852C2 cmp [ebp-4],0Ah ; 10 000852C6 je 00085339 ; x == 10 000852C8 cmp [ebp-4],32h ; 50 000852CC je 0008534B ; x == 50 000852CE jmp 000853D5 ; default

结合逻辑:

if(x<1000){if(x>100){// 200, 500 分支}elseif(x==100){// case 100}elseif(x==10){// case 10}elseif(x==50){// case 50}else{// default}}

再看x > 100的那条分支:

000852D3 cmp [ebp-4],0C8h ; 200 000852DA je 0008536C ; case 200 000852E0 cmp [ebp-4],1F4h ; 500 000852E7 je 0008537B ; case 500 000852ED jmp 000853D5 ; default

所以小于 1000 的区间逻辑就是一个两层 if-else 树,把 10、50、100、200、500 分开。


5. 大于 1000 的分支

回到第一层x > 1000

000852F2 cmp [ebp-4],2710h ; 10000 000852F9 jg 00085327 ; x > 10000 → 后续分支 000852FB cmp [ebp-4],2710h 00085302 je 000853B7 ; case 10000 00085308 cmp [ebp-4],7D0h ; 2000 0008530F je 00085399 ; case 2000 00085315 cmp [ebp-4],1388h ; 5000 0008531C je 000853A8 ; case 5000 00085322 jmp 000853D5 ; default

逻辑对应 C:

if(x>1000){if(x>10000){if(x==20000)printf("20000\n");elseprintf("default\n");}else{if(x==10000)printf("10000\n");elseif(x==2000)printf("2000\n");elseif(x==5000)printf("5000\n");elseprintf("default\n");}}

可以看到编译器在大数区间也做了分区+二分比较


6. case 分支实现细节

每个 case 基本一样,都是 push 字符串地址,call printf,然后跳到 switch 尾部。例如:

00085339 push 88620h ; "10\n" 0008533E call 00081082 ; printf 00085343 add esp,4 00085346 jmp 000853E2 ; switch 尾部

其它 case 也类似,只是字符串地址不同。default 也是一样:

000853D5 push 88668h ; "default\n" 000853DA call 00081082 000853DF add esp,4

尾部统一处理函数返回。


7. 从汇编“还原”成等价 C

把所有比较和跳转串起来,就像在画一棵决策树,最终等价 C 代码如下:

voidbinary_search_switch(intx){if(x>1000){if(x>10000){if(x==20000)printf("20000\n");elseprintf("default\n");}else{if(x==10000)printf("10000\n");elseif(x==2000)printf("2000\n");elseif(x==5000)printf("5000\n");elseprintf("default\n");}}elseif(x==1000){printf("1000\n");}else{if(x>100){if(x==200)printf("200\n");elseif(x==500)printf("500\n");elseprintf("default\n");}else{if(x==100)printf("100\n");elseif(x==10)printf("10\n");elseif(x==50)printf("50\n");elseprintf("default\n");}}}

仔细看会发现,这完全对应汇编里的 cmp + 条件跳转组合,编译器就是把稀疏 case 值分层,减少比较次数。


8. 为什么说这是“折半查找 / 二分搜索风格”

总结规律:

  1. 第一层用1000把所有 case 分成<1000==1000>1000三块。

  2. <1000区间再用100{10,50,100}{200,500}分开。

  3. >1000区间用10000{2000,5000,10000}{20000}分开。

整个结构就像一棵高度 3~4 的决策树。相比线性 if-else:

  • 线性比较最坏要 9 次

  • 现在最坏只要 3~4 次

同时避免了跳转表对稀疏 case 的巨大空间浪费。


9. 逆向工程实战经验

下次再看到类似汇编,识别方法:

  1. 一连串cmp [ebp-4], imm+jg/jl/je→ 明显按大小分段。

  2. 分支里直接push 常量 → call printf → jmp 统一尾部→ 这就是 case。

  3. 多处jmp 同一个尾部→ switch 的统一出口。

  4. 没有 jump table 的连续指针数组 → 编译器用了比较树而不是 table。

看到这些,基本可以断定是二分搜索风格 switch


10. 测试示例

#include<stdio.h>voidbinary_search_switch(intx){switch(x){case10:printf("10\n");break;case50:printf("50\n");break;case100:printf("100\n");break;case200:printf("200\n");break;case500:printf("500\n");break;case1000:printf("1000\n");break;case2000:printf("2000\n");break;case5000:printf("5000\n");break;case10000:printf("10000\n");break;case20000:printf("20000\n");break;default:printf("default\n");break;}}intmain(){binary_search_switch(100);binary_search_switch(5000);binary_search_switch(300);// defaultreturn0;}

运行结果与汇编逻辑完全一致。


总结

通过这次分析,我又巩固了几个点:

  • 稀疏、按序但跨度大的 switch case,编译器常用二分搜索风格的比较树

  • 汇编里连续cmp + 条件跳转 + push/ call + jmp是典型特征。

  • 这种结构在逆向工程中非常好认,而且可以快速还原出等价 C 代码,理解程序逻辑。

这比直接看 jump table 更直观,也更节省空间。


本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/1141044.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

wpf自定义控件 ToggleButton_Checked事件怎么防止鼠标滚动误触发

<!-- HandyControl 局部指定控件使用&#xff0c;防止覆盖默认样式 --> <UserControlx:Class"Module.PEIS.ZhiYeBingTiJian.View.ToggleButtonCustuom"xmlns"http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x"http://s…

强烈安利!10款AI论文网站测评,本科生毕业论文必备

强烈安利&#xff01;10款AI论文网站测评&#xff0c;本科生毕业论文必备 为什么你需要这份AI论文网站测评&#xff1f; 随着人工智能技术的快速发展&#xff0c;越来越多的本科生开始依赖AI工具辅助完成毕业论文写作。然而&#xff0c;面对市场上五花八门的AI论文网站&#xf…

archlinux 如何调整 笔记本内置屏幕的亮度

使用命令行工具&#xff08;推荐&#xff09; 这是最稳定、最通用的方法。 brightnessctl: 目前最流行且轻量化的工具。 安装: sudo pacman -S brightnessctl 查看设备: brightnessctl -l 调高亮度: brightnessctl set 10% 调低亮度: brightnessctl set 10%- 提示&#xff1a;该…

基于SpringBoot的群众网上高效办事系统的设计与实现(源码+lw+部署文档+讲解等)

课题介绍随着“互联网政务服务”战略深入推进&#xff0c;群众对便捷、高效政务服务的需求日益迫切&#xff0c;但当前政务服务工作普遍存在办事流程繁琐、线下跑动次数多、审批效率低下、事项信息不透明、进度查询不便等问题&#xff0c;制约了政务服务质量与群众满意度的提升…

阳明交通大学突破:动态视频重建技术实现画质动作双优化

台湾阳明交通大学的詹杰文、刘宇伦团队&#xff0c;联合西班牙萨拉戈萨大学的赵振军&#xff0c;在2025年1月发表了一项名为"AdaGaR: Adaptive Gabor Representation for Dynamic Scene Reconstruction"的突破性研究。这项研究被arXiv收录&#xff0c;论文编号为arXi…

一键生成AI播客

随着AI技术的快速发展&#xff0c;一键生成AI播客已成为内容创作者、知识工作者和普通用户的重要工具。这类平台通过先进的语音合成技术和自然语言处理能力&#xff0c;能够将文本、网页链接或文档快速转化为自然流畅的播客音频&#xff0c;极大降低了内容创作门槛。本文将深入…

伯克利团队破解AI评测难题:让机器学会自动出题的神奇方法

这项由加州大学伯克利分校的Ishir Garg、Neel Kolhe、Xuandong Zhao和Dawn Song领导的研究发表于2026年1月&#xff0c;有兴趣深入了解的读者可以通过论文编号arXiv:2601.00575v1查询完整论文。要理解这项研究的重要性&#xff0c;不妨先考虑一个日常场景&#xff1a;老师们每次…

腾讯优图Youtu-Agent:AI代理实现自动化生成突破

这项由腾讯优图实验室联合复旦大学和厦门大学共同完成的研究发表于2025年12月26日&#xff0c;论文编号为arXiv:2512.24615v1。研究团队由石宇宸、蔡宇正、蔡思琪等多位研究者组成&#xff0c;他们致力于解决当前大语言模型代理框架中的两大核心挑战。有兴趣深入了解的读者可以…

构建个人知识库工具分类与对比

在信息爆炸的2026年&#xff0c;个人知识库已成为知识工作者不可或缺的工具。它不仅帮助我们有效管理碎片化信息&#xff0c;还能通过结构化整理促进知识迁移与创新。本文将从功能特点、适用场景、核心优势三个维度&#xff0c;系统分析当前主流的个人知识库平台/软件/网站&…

商汤突破:全能AI助手集成搜索识图与自主思考

由SenseTime研究院、清华大学以及中科大联合开展的一项突破性人工智能研究在2025年1月1日发表。这项名为"SenseNova-MARS: Empowering Multimodal Agentic Reasoning and Search via Reinforcement Learning"的研究&#xff0c;开发出了一个真正意义上的"全能AI…

中药材原料口碑排行榜:哪些药材最受欢迎?

中药材原料哪家好&#xff1a;专业深度测评开篇&#xff1a;定下基调随着人们对健康和自然疗法的关注日益增加&#xff0c;中药材原料的需求也在不断增长。为了帮助大家更好地选择高质量的中药材原料&#xff0c;我们对市场上主要的中药材供应商进行了深入测评。本次测评的主要…

KAIST团队突破虚拟对话新纪元:让AI头像像真人一样自然互动

这项由韩国科学技术院&#xff08;KAIST&#xff09;的奇泰炅&#xff08;Taekyung Ki&#xff09;、张相元&#xff08;Sangwon Jang&#xff09;等研究者与新加坡南洋理工大学和DeepAuto.ai公司合作完成的突破性研究&#xff0c;发表于2026年1月的arXiv预印本平台&#xff0c…

《揭秘 AI 应用架构师运用 AI 驱动生产计划的核心算法》

揭秘 AI 应用架构师运用 AI 驱动生产计划的核心算法 一、引入&#xff1a;当生产计划遇到“黑天鹅”——从混乱到秩序的AI救赎 凌晨3点&#xff0c;某电子制造工厂的生产总监盯着电脑屏幕上的红色警报&#xff0c;额角渗出冷汗&#xff1a; 海外客户突然追加5000台智能手机订单…

清华大学团队突破AI视频理解难题:用“反常识“训练让机器看懂真相

这项由清华大学的黄哲、北京航空航天大学的文浩&#xff0c;以及阿里巴巴地图团队的郝爱鸣、宋兵泽等研究者共同完成的研究&#xff0c;发表于2025年12月30日的arXiv预印本平台&#xff0c;论文编号为arXiv:2512.24271v1。有兴趣深入了解的读者可以通过该编号查询完整论文。当前…

武汉市放飞炬人产业引导基金:将起草 房地产转让工业信托基金 合同草书

武汉市放飞炬人产业引导基金&#xff1a;将起草 房地产转让工业信托基金 合同草书

剑桥大学最新突破:让AI既聪明又富有创造力的秘诀

这项由英国剑桥大学的Max Ruiz Luyten和Mihaela van der Schaar教授团队开展的突破性研究发表于2026年1月2日&#xff0c;论文编号为arXiv:2601.00747v1。对这一前沿研究感兴趣的读者可以通过该编号查阅完整论文。这项研究首次解决了当前大型语言模型训练中面临的一个核心矛盾&…

python中各种数据类型的转换方法

近期在做网络协议相关的开发&#xff0c;学习了一些数据转换方法&#xff0c;在此记录一下1. 网络协议中&#xff0c;用的最多的就是 struct.pack和 struct.unpack&#xff0c;一个是打包&#xff0c;一个解包&#xff0c;它有一个其他模块都没有的功能就是它可以把整形&#x…

腾讯天美AI团队重新定义语言模型训练:精确还是多样?

这项由腾讯天美LLM部门的吴浩源、王海等研究人员以及香港中文大学的于贝教授合作完成的研究发表于2025年12月&#xff0c;论文编号为arXiv:2512.22955v1。有兴趣深入了解的读者可以通过该编号查询完整论文。 当我们日常与聊天机器人对话时&#xff0c;可能从未想过这样一个问题…

救命神器8个AI论文软件,助你轻松搞定本科毕业论文!

救命神器8个AI论文软件&#xff0c;助你轻松搞定本科毕业论文&#xff01; AI 工具助力论文写作&#xff0c;轻松应对学术挑战 在当今信息化时代&#xff0c;AI 技术已经深入到各个领域&#xff0c;教育行业也不例外。对于本科生而言&#xff0c;撰写毕业论文是一项既重要又复杂…

FreeSWITCH 简单图形化界面51 - 拨号应用 Bridge 介绍

FreeSWITCH 简单图形化界面51 - 拨号应用 Bridge 介绍00、 一个fs的web配置界面预览01、 Web 配置界面预览02、 Web界面安装参考FreeSWITCH 核心应用详解&#xff1a;mod_dptools: bridge1. 核心概念1.1 bridge 与 uuid_bridge 的区别1.2 基本语法bridgeuuid_bridge2. 目标端点…