Assembly 什么构成基本块的开始?

Assembly 什么构成基本块的开始?,assembly,x86,x86-64,Assembly,X86,X86 64,汇编代码无条件跳转后的指令是否构成新基本块的开始?假设指令不是可执行文件中任何分支的目标。遵循无条件跳转且不是任何分支或跳转的目标的指令是死代码或简单的数据。由于计算分支的可能性,条件分支可能总是或永远不会被遵循,不可能完全确定什么构成基本块。相反,使用两个假设来估计基本区块: 由于其他原因,计算出的分支只会到达基本块的开始位置,因此不需要知道它们的目标 条件分支既可以跟随也可以不跟随 使用,基本块只能在开始时输入,在结束时退出,从开始到结束只有一条路径。因此,任何条件跳转指令都必须是基本块的结

汇编代码无条件跳转后的指令是否构成新基本块的开始?假设指令不是可执行文件中任何分支的目标。

遵循无条件跳转且不是任何分支或跳转的目标的指令是死代码或简单的数据。

由于计算分支的可能性,条件分支可能总是或永远不会被遵循,不可能完全确定什么构成基本块。相反,使用两个假设来估计基本区块:

  • 由于其他原因,计算出的分支只会到达基本块的开始位置,因此不需要知道它们的目标
  • 条件分支既可以跟随也可以不跟随
  • 使用,基本块只能在开始时输入,在结束时退出,从开始到结束只有一条路径。因此,任何条件跳转指令都必须是基本块的结尾,因为它创建了两条路径。计算分支也是终点,因为它们可以生成许多不同的路径

    无条件跳转是否是基本块的结束可以使用稍微不同的定义进行辩论。如果一个块中的所有代码在内存中必须是顺序的,那么无条件跳转总是结束,除非它转到后面的指令。否则,它将遵循与非跳转指令相同的规则

    对于所有其他指令,如果将在其之后执行的指令是基本块的开始,则它必须是基本块的结束

    块的最简单开始是程序的入口点。此外,任何作为条件跳转目标的指令都是块的开始,因为它可能在跳转指令之后执行,也可能不执行。如果指令是无条件跳转的目标,并且基本块在内存中必须是顺序的,那么它就是块的开始。否则,如果它是两个或多个无条件跳转的目标,或者它是一个跳转的目标,并且它之前的指令不是无条件跳转,那么它是一个块的开始,因为有多条路径进入它

    如果无条件跳转后的指令不是任何其他跳转的目标,它仍然可能被标记为基本块的开始,因为它的存在表明计算分支可能以它为目标

    这些基本块开始的规则本质上简化为“在基本块结束后执行的指令是基本块的开始”

    一种更简单的方法,有时可能产生更小的块,但通常是好的,即任何跳转都是一个块的结束,它后面的指令是一个块的开始,而任何跳转的目标是一个块的开始,它前面的指令是一个块的结束


    如果有更高级别的代码可用,则可以使用它更准确地确定块边界。例如,编译器生成的计算分支通常具有一组已知的可能目标。考虑下面的C代码:

    inti,j,k;
    开关(一){
    案例0:
    j++;
    //流入下一个案例
    案例1:
    k++;
    }
    
    下面是此代码使用计算分支的一些可能的伪程序集:

    jump*(i+jumpTable)
    加1,j
    加1,k
    

    跳转表将以一条add指令为目标,因此它们都是基本块的开始。但是,这无法从程序集确定,因此使用第一个假设。第一次添加是一个基本块的开始,因为它是在跳转之后进行的。但是,没有针对第二个add的已知分支,因此此分析不认为它是基本块的开始。

    分析汇编代码以尝试定位块是否有意义?该指令无法以任何正常方式到达(除非中途跳转到前面的无条件跳转中,并希望一切正常)所以在某些方面,它甚至不是“代码”,只是数据。@CarlNorum-是的,它是。重建节点为基本块的CFG是静态二进制分析的第一步。定义“基本块”。程序集“代码块”可以按照您希望的逻辑定义。汇编语言本身并没有定义的块结构。根据该定义,无条件跳转可能形成也可能不形成“基本块”,这取决于代码在做什么以及跳转的原因。诸如“理想的”和“高度顺从的”之类的短语有点主观。弄清楚这一点可能很困难,因为跳转目的地可以嵌入跳转表中,甚至可以动态计算。@BrianKnoblauch-准确地说。有时,使用纯静态方法从可执行文件生成完整的CFG是困难的或不可能的。@BrianKnoblauch-我完全同意。分析可执行代码,猜测什么是数据,什么是代码本身,这并不是一项简单的任务。