avatar

6.6日更新 (week 7)

小黄书更新

分支优化规则

配合流水线的工作模式,处理器增加了一个分支目标缓冲器,在流水线的工作模式下,如果遇见分支结构,我们就可以利用分支目标缓冲器预测并且读取指令的目标地址,分支目标缓冲器在程序运行的时候将动态记录和调整转移指令的目标地址,可以记录多个地址,进行表格化的管理,当发生转移的时候秒如果分支目标缓冲器中有记录,下一条指令在取指令阶段就会将其作为目标地址,如果我们记录地址不等于实际目标地址,就会被流水线冲刷,用一个分支,多次与邪恶失败,就会更新记录目标地址,所以我们在编写多重循环的时候,要把大循环放在内层,可以增加分支预测的准确度

1
2
3
4
5
6
7
8
for(int i=0; i < 10; i++){
//下面每次循环会预测成功9999次
//第一次没有预测,最后退出循环的时候预测失败1次
//重复10次
for(int j = 0 ; j < 10000 ; j++){
a[i][j]++;
}
}
1
2
3
4
5
6
7
8
for(int i=0; i < 10000; i++){
//下面每次循环会预测成功9次
//第一次没有预测,最后退出循环的时候预测失败1次
//重复10000次
for(int j = 0 ; j < 9 ; j++){
a[i][j]++;
}
}

所以说大循环在里面可以增加分支预测准确度

高速缓存 ( cache ) 优化规则

计算机内存的访问效率低于处理器,而且在程序的运行中,于是乎处理器准备了 cache来存放需要经常访问的数据和代码,这些数据内存用VA以表格方式一 一对应,从处理器访问内存数据时候,要去cache中看看这个VA有没有记录,如果有,则名终,就不需要访问内存单元,如果没有找到,就转换VA访问数据,然后保存到cache中,一般来说,cache会把读取指令需要的数据以及附近的数据都读取进来,从而节省cache宝贵的空间,VA值的二进制低位不会被保存,所以保存的数据是2^n字节为单位的

cache优化:

  1. 数据对齐
  2. 数据集中
  3. 减少体积

流程控制语句的识别

if语句

if语句只能判断两种情况:"0"为假,"非0"为真,if语句转换的条件跳转指令与if语句的判断结果是相反的

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
//C++源码说明:if语句结构组成
if( argc == 0 ){
printf("%d \r\n", argc);
}
//C++源码对应汇编
//如果argc = 0的情况,为真
if( argc == 0 )
//使用cmp指令,将ebp+8地址的4字节和0相减
//结果argc不改变,淡水会改变CF,ZF,OF,AF和PF
00401028 cmp dword ptr [ebp+8],0
//JNE看ZF,如果等于0跳转,表示现在的argc不等于0
//跳转到0x40103F
//这个地址为if的结束地址,之后跳转出if
0040102C jne main+2F(0040103f)
{
//printf略
}
//函数返回
return 0;
0040103F xor eax,eax

JNE代表了,ZF=0 跳转,当前代码也就是argc不等于0就跳转,正常我们的c语言来说是满足if的条件执行语句块,汇编中是满足某条件进行跳转,与C语言相反

因为我们C语言中,是根据我们代码行的位置来决定编译后二进制的高低,也就是低行数对应低地址,高行数,对应高地址,那么根据这个特性,如果我们是 argc > 0 ,那么跳转的条件就是小于等于0是否满足,满足的不跳转

1
2
3
4
5
6
7
8
9
10
11
12
13
14
//C++源码说明: if语句大于0比较
if( argc > 0 ){
printf("%d \r\n",argc);
}
//C++源码对应汇编代码
//C++源码对比,如果参数argc大于0,结果为真,进入执行语句
if(argc > 0)
//使用cmp,将ebp+8地址的4字节数据和0进行减法
0040103F cmp dword ptr [ebp+8],0
00401043 jle MyIf + 42h (00401052)
{
//printf略
}
00401052 pop edi

我们在使用反汇编的时候,表达式短路和if语句想像,实现的结构类似

if…else…语句

两种结构的对比

image-20200607004352276

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
//C++源码说明: if  else
if(argc == 0){
printf("argc = 0");
}
else{
printf("argc != 0");
}
//对应汇编
004010B8 cmp dword ptr [ebp+8],0 //相减
004010BC jne IfElse+2Dh (004010cd){
//printf 略
}
004010CB jmp IfElse+3Ah (004010da)
{
//进入else
004010CD push offset string "argc != 0" (00420030)
004010D2 call printf (00401150)
004010D7 add esp,4
}
//结束
004010DA pop edi

正常流程和if差不多,这里纠正了自己的一个思想,就是跳转的时候,也是比较

Author: L0x1c
Link: https://l0x1c.github.io/2020/06/06/2020-6-06/
Copyright Notice: All articles in this blog are licensed under CC BY-NC-SA 4.0 unless stating additionally.
Donate
  • 微信
    微信
  • 支付寶
    支付寶