周宁县建设局网站,wordpress+链接跳转,企业网络营销策划方案设计的例子,建设摩托车价格大全滴水逆向三期笔记与作业——02C语言——10 Switch语句反汇编 一、Switch语句1、switch语句 是if语句的简写2、break加与不加有什么特点?default语句可以省略吗#xff1f;3、游戏中的switch语句#xff08;示例#xff09;4、添加case后面的值#xff0c;一个一个增加3、游戏中的switch语句示例4、添加case后面的值一个一个增加观察反汇编代码的变化(何时生成大表).5、将3中的常量值的顺序打乱观察反汇编代码(观察顺序是否会影响生成大表).6、将case后面的值改成从100开始到109连续观察汇编变化(观察值较大时是否生成大表).7、将连续的10项中抹去1项或者2项观察反汇编有无变化(观察大表空缺位置的处理).8、在10项中连续抹去不要抹去最大值和最小值(观察何时生成小表).9、将case后面常量表达式改成毫不连续的值观察反汇编变化.10、部分连续部分差值非常大 二、do/while反汇编1、do/while的语法2、do/while的反汇编3、example4、总结 三、while反汇编1、while语句的语法2、while语句反汇编3、example4、总结 四、for循环反汇编1、for语句的语法2、for循环的执行次序3、example4、总结 五、作业1、写一个Switch语句不生产大表也不生产小表贴出对应反汇编2、写一个Switch语句只生成大表贴出对应反汇编3、写一个Switch语句生成大表和小表贴出对应反汇编4、为do/while语句生成的反汇编填写注释5、为while语句生成的反汇编填写注释6、为for语句生成的反汇编填写注释 一、Switch语句
1、switch语句 是if语句的简写
if语句
if(表达式 常量1)
{//...代码
}
else if(表达式 常量2)
{//...代码
}
else if(表达式 常量3)
{//...代码
}
else
{//...代码
}
switch语句
switch(表达式)
{ case 常量表达式1语句;break;case 常量表达式2语句;break;case 常量表达式3语句;break;case 常量表达式3语句;break;default: 语句;break;
}switch要求
1、case后面必须是常量表达式
2、case后常量表达式的值不能一样
3、switch后面表达式必须为整数
2、break加与不加有什么特点?default语句可以省略吗
不写break时编译可以通过但会将不写break的case全部执行一遍。 default语句可以省略当所有条件都不满足的时候会默认执行default中的代码如果不存在default但所有条件不满足则不执行代码。
3、游戏中的switch语句示例
F1 F2 F3 F4 F5 F6 F7 F8
0 1 2 3 4 5 6 7
switch(表达式)
{case 1:打坐....break;case 2:加红.... break;case 3:加蓝.... break;case 4:释放技能....break;default:语句;break;
}
4、添加case后面的值一个一个增加观察反汇编代码的变化(何时生成大表).
我的环境是64位的vscode与海哥教程中存在较大差异。
少分支Switch结构
void Function(int x){
switch (x){
case 1:
printf(1);
break;
case 2:
printf(2);
break;
case 3:
printf(3);
break;
default:
printf(4);
break;
}
}int main(int argc, char* argv[]){
Function(2);return 0;
} 由汇编可见少分支的Switch与if相似所以正向代码中分支较少时建议不使用Switch
多分支Switch结构
void Function(int x){
switch (x){
case 1:
printf(1);
break;
case 2:
printf(2);
break;
case 3:
printf(3);
break;
case 4:
printf(4);
break;
default:
printf(5);
break;
}
}int main(int argc, char* argv[]){
Function(2);return 0;
} 未发现大表寻址过程
多分支Switch结构
void Function(int x){
switch (x){
case 1:
printf(1);
break;
case 2:
printf(2);
break;
case 3:
printf(3);
break;
case 4:
printf(4);
break;
case 5:
printf(5);
break;
case 6:
printf(6);
break;
default:
printf(7);
break;
}
}
int main(int argc, char* argv[]){
Function(3);
return 0;
} 存在大表寻址过程已优化
总结 1、分支少于4的时候使用Switch没有意义因为编译器会生成类似if/else之类的反汇编 2、case后面的常量表达式可以是无序的并不影响大表的生成
• 分支较少时不生成大表也不生成小表会生成if…else语句 • 分支达到一定数量时生成大表且大表跟顺序无关 • 大表可以理解为一个存储了多个地址的连续表通过Register*4可以来寻址。 • 分支达到一定数量生成大表但是中间缺少很多case时,还会生成一张小表。 • 小表的作用可以理解为把大表的空缺地址移动到了小表把空缺的case值所在的地方填为default的地址
5、将3中的常量值的顺序打乱观察反汇编代码(观察顺序是否会影响生成大表).
并不影响大表生成
6、将case后面的值改成从100开始到109连续观察汇编变化(观察值较大时是否生成大表).
代码
void Function(int x){
switch (x){
case 100:
printf(100);
break;
case 101:
printf(101);
break;
case 102:
printf(102);
break;
case 103:
printf(103);
break;
case 104:
printf(104);
break;
case 105:
printf(105);
break;
case 106:
printf(106);
break;
case 107:
printf(107);
break;
case 108:
printf(108);
break;
default:
printf(109);
break;
}
}
int main(int argc, char* argv[]){
Function(103);
return 0;
}
反汇编
如果[参数-100]大于[max-min]说明传入参数小于case最小值或者大于case最大值此时直接执行default即可 反之说明参数在min到max之间而此时eax中存储的是[参数-100]的数值而编译器已经维护了一张表根据eax的位置像一维数组查数一样根据公式eax基址eax代表的内存的数据跳转到eax的执行地址即可jmp rax。
7、将连续的10项中抹去1项或者2项观察反汇编有无变化(观察大表空缺位置的处理). 被删除的部分并不会被填充0大表会把抹去的分支项原先所对应的地址全部给填充为default默认地址.
8、在10项中连续抹去不要抹去最大值和最小值(观察何时生成小表).
小表是将大表的地址移动到小表空缺的地方填充为到default的偏移量。 海哥的教程中删除一定的case分支后生成小表但本地环境win64VSCOde中未生成小表删除一定的分支后直接转换成if/else形式我也很疑惑……。
9、将case后面常量表达式改成毫不连续的值观察反汇编变化.
类似于if/else的结构
10、部分连续部分差值非常大
代码
void Function(int x){
switch (x){
case 300:
printf(300);
break;
case 301:
printf(301);
break;
case 302:
printf(302);
break;
case 303:
printf(303);
break;
case 304:
printf(304);
break;
case 305:
printf(305);
break;
case 306:
printf(306);
break;
case 307:
printf(307);
break;
case 3:
printf(3);
break;
default:
printf(309);
break;
}
}
int main(int argc, char* argv[]){
Function(303);
return 0;
}
反汇编 与if/else相同下图为海哥教程图
二、do/while反汇编
1、do/while的语法
do
{//执行代码
}while(表达式)
2、do/while的反汇编 3、example 4、总结
根据条件跳转指令所跳转到的地址可以得到循环语句块的起始地址。根据条件跳转指令所在的地址可以得到循环语句块的结束地址。条件跳转的逻辑与源码相同。
三、while反汇编
1、while语句的语法
while(表达式)
{//执行代码
}2、while语句反汇编 3、example 4、总结
根据条件跳转指令所跳转到的地址可以得到循环语句块的结束地址根据jmp 指令所跳转到的地址可以得到循环语句块的起始地址在还原while 比较时条件跳转的逻辑与源码相反。
四、for循环反汇编
1、for语句的语法
for(表达式1表达式2表达式3) { //执行的代码 }
2、for循环的执行次序
表达式1 表达式2 执行的代码(大括号里面的内容) 表达式3
表达式2 //如果表达式2成立 执行的代码(大括号里面的内容) 表达式3
表达式2 //如果表达式2成立 执行的代码(大括号里面的内容) 表达式3
表达式2 //如果不成立 跳出循环
3、example 4、总结
第一个jmp 指令之前为赋初值部分第一个jmp 指令所跳转的地址为循环条件判定部分起始判断条件后面的跳转指令条件成立时跳转的循环体外面条件判断跳转指令所指向的地址上面有一个jmp jmp地址为表达式3的起始位置
五、作业
1、写一个Switch语句不生产大表也不生产小表贴出对应反汇编
void Function(int x)
{
switch(x)
{
case 1:printf(1);break;
case 2:printf(2);break;
case 3:printf(3);break;
default:printf(Error);break;
}
}int main(int argc, char* argv[]){Function(2);return 0;
}2、写一个Switch语句只生成大表贴出对应反汇编
void Function(int x)
{
switch(x)
{
case 1:printf(1);break;
case 2:printf(2);break;
case 3:printf(3);break;
case 4:printf(4);break;
case 5:printf(5);break;
case 6:printf(6);break;
default:printf(Error);break;
}
}int main(int argc, char* argv[]){
Function(5);return 0;
}3、写一个Switch语句生成大表和小表贴出对应反汇编
void Function(int x)
{
switch(x)
{
case 100:printf(100);break;
case 101:printf(101);break;
case 110:printf(110);break;
case 3:printf(3);break;
case 1:printf(1);break;
default:printf(Error);break;
}
}
int main(int argc, char* argv[]){Function(101);return 0;
}我的是if/else结构博客站中是大小表结构。
4、为do/while语句生成的反汇编填写注释
void Function(int i)
{do{printf(%d\n, i);i;} while (i3);}
int main(int argc, char* argv[]){Function(0);return 0;
}5、为while语句生成的反汇编填写注释
void Function(int i)
{while (i3){printf(%d\n, i);i;}}
int main(int argc, char* argv[]){Function(0);return 0;
} 6、为for语句生成的反汇编填写注释
void Function(int x)
{for (int i 0; i x; i){printf(%d\n, i);}
}
int main(int argc, char* argv[]){Function(5);return 0;
}