继续上次的话题讲一下程序流控制汇编。
C和汇编代码中的语句,默认的方式是顺序的控制流,按照语句或者指令在程序中出现的顺序方式进行。
而某些程序结构,如Switch语句,循环语句和分支语句,则不尽然。
首先介绍CPU中一组单个位的条件码(condition code)寄存器,它们描述了最近的算术或者逻辑操作属性。
一般涉及的条件码:
CF: 进位标志
ZF: 零标志
SF: 符号标志
OF: 溢出标志
对于cmpb, cmpw, cmpl (S2, S1), 指令根据S1-S2的差来设置条件码。
而testb, testw, testl (S2, S1), 指令根据 S1 AND S2来设置条件码。
至于跳转指令,如jmp, jbe, js 等
这里不介绍具体细节,可以自行阅读汇编或者接口相应表格部分。
下面我们就可以来说一些GAS有意思的地方。
下面jbe指令的目标地址是?
8048D1C: 76 DA jbe xxxxxxx
8048D1E: EB 24 jmp 8048d44
解读上面的小题需要理解:
当执行与PC相关的寻址时,程序计数器的值是跳转指令后面的那条指令的地址。
另外,对于存放在2内存中的2进制指令,"76 DA" 来说,后面的0xDA就是我们常常说的偏移量。
于此一来,我们可以计算出 xxxxxxx = 0x8048D1E + 0x00000DA = 0x8048DF8
此外还有一些Tips:
1. 编译器对代码的优化,常常会自己设置新参数,而修改条件判别式,来减少参数和2进制指令个数
2. 对于阅读控制流的汇编码,尽量先转换成while型,而后转换成goto型,事实上,编译器大多时候都是这样设计的。
3. while() {} 语句常常在机器码级被转换成一条判断和 do {} while () 的方式,所以养成习惯写后者(…真的需要这样吗?)