跳转指令跳转指令也是一组指令,称为j组。其中jmp为无条件跳转,其余为条件跳转。上图为j组指令,可以结合条件码访问指令加深理解。了解如何在机器命令级别对跳转指令进行编码。汇编语言,其中左边是机器指令的代码,右边是对应汇编语言的意思,最左边是每条机器指令的地址。jmp指令对应的机器指令有两个字节:eb表示这是一条jmp指令,03描述跳转信息。值得注意的是,跳转指令编码时,使用的是相对位置编码,03中介绍,偏移结合例子理解:jmp指令未执行时,rip寄存器存放的地址为4004d5(rip寄存器存放待加载指令地址);jmp指令执行后,rip寄存器的值变为新的目标位置地址,目标位置=原位置+偏移量,本例为4004d5+03=4004d8。jg指令中存储相对位置的意义是一样的:可以获得更高的灵活性。如果存储绝对地址,分配的地址可能会改变;但相对位置不能改变。利用汇编语言的跳转指令实现C语言的条件分支,如上图所示,左边的程序可以通过上面的指令翻译成汇编指令。上面指令的理解:control.c是输入文件-s表示将c语言程序翻译成汇编指令-og是程序优化的一种形式。这种形式的优化程度较低,但在不改变程序原有结构的情况下进行了优化,因此可以更清楚地看出程序设计语言与汇编语言之间的关系。在实际应用中,-o1和-o2更加优化,可以更大程度的提升程序性能,尤其是-o2已经成为了现在的主流标准。但是这两种形式可能会改变原来高级语言的语句结构,高级语言和汇编指令之间很难建立映射关系,所以不要用-fno-if-conversion来告诉编译器编译时,不要使用branch语句,用条件转移指令和跳转指令执行。在早期的X86处理器中,分支语句只用跳转指令表示,后来又增加了条件转移指令。现在很多处理器都使用条件转移指令来表示分支语句。使用条件数据传输指令来实现条件分支。条件数据传输指令,首先计算条件的结果,然后根据条件结果的具体状态,决定是否将原操作数的值赋给目标操作数。它类似于传统的mov指令,但相当于在mov指令之前判断条件。如果条件不符合要求,怎么办?没有任何;满足要求,执行赋值既然已经有了跳转指令,为什么要引入条件数据传输指令:跳转指令存在性能问题。处理器架构中有流水线技术,可以实现指令执行的加速。但是流水线必须进行指令的预取,通常的预取策略是顺序寻址。如果遇到跳转指令,无法提前判断是否执行跳转,导致跳转指令对流水线指令的预取具有破坏意义。尽管流水线做了很多工作来避免破坏性(比如分支预测),但是任何数量的补偿都会导致程序性能下降。条件数据传输指令会预先计算条件,然后判断是否赋值(即是否执行赋值指令),从而避免损坏流水线。虽然增加了计算量,但是流水线性能的优化要高于计算性能的代价。组合示例指令为跳转指令,去除-fno-if-conversion条件数据传输指令过程:先计算一种情况的结果(x-y)。,并将其放入rax寄存器;另一个也被计算并放入rdx寄存器;然后在比较x和y的大小时使用cmov指令组,类似于set指令组。比如cmovle小于等于,则将rdx赋值给rax;如果大于,保持原来的状态。条件数据转移指令可以很好的优化性能,但是并不是所有的条件数据分支都可以用条件语句来表达,如下图,分支语句块包含非常繁重的计算,导致计算开销远大于优化管道性能。风险情况。例如,取p指针指向的值的操作必须在p不为0的前提下进行。条件数据传输指令会先计算这两个结果,然后进行取舍。此时如果p指针不存在,可能会导致计算出错,并且可能产生副作用,即使用的变量相互关联。两个结果都会更新x。如果使用条件数据传输指令先计算结果,x的值会发生变化,这与原来的逻辑不一致。关注公众号,让我们一起努力
