首先要知道Basic Block是什么。是一段线性程序,这段代码里面没有分支,只有一个入口和一个出口。划分basic blocks,首先要找到leaders(入口语句):
- 程序的第一条语句
- goto语句的目标语句(statement)。比如下面代码第6行?
- goto后面紧跟着的语句。比如下面代码第8、10行?
然后就是根据leaders来划分basic blocks:
- 所有跟在leader后面到下一个leader出现前的语句
- 第一个语句叫做first leader
- 包含first leader的block叫做initial block
一个basic block只有一个入口,只能从这一个入口进到这个basic block里面并且执行它的代码
一个basic block只有一个出口,这个basic block里的最后一句跑完了之后就得去下一个basic block?
以下面的binary search 为例。如果按照这个划分,那下面iterativeBinarySearch的basic blocks就是(3-6), (7-8), (9-10), (11-12)?
Control-flow graph是一个流程图,它表示的是程序执行时候的顺序。CFG里面每个node都是一个basic block。下图就是用ida生成的上面的代码的control flow graph,这个graph里面每一个小方块都是一个basic block。
具体看看:
- 第一个basic block就是function开始的basic block。里面的 %rbp 是栈帧指针frame pointer,用于标识当前栈帧的起始位置。通常就是函数的起点了。
- while循环其实是source code的第三行,但在basic block里面却被拆开成了两个basic blocks。因为在while循环初始化阶段,会有start_index, end_index的初始化,就是第一个basic block里面的mov那几行。但它们只在while循环初始化的时候执行一次,因为后面在循环回来的时候,这些参数就已经设置好了,不能反复初始化。同理for loop也是一样的。
- 然后我们看右下角line13的block其实是exit basic block。起点的%rbp被pop出去了,代表这个函数就彻底结束了。有两条edge通向这个block,分别是从第6行和第12行出来的。因为6和12行都是return语句。
- source code第9行为什么没有出现在图里呢?因为这个代码其实是我写的,个人习惯把else后面接的命令另起一行。其实把第9,10行合并成一行也是可以的。所以在现有的代码下,9行的else就是一个edge,并不是一个basic block。