SET指令根据条件码或者条件码的组合来将一个字节设置为0或1(所以如果set指令后面跟的是寄存器,那么必须是单字节的寄存器)。
在经过了比较指令a 分析有符号数的4种指令。
1)分析setl
。因为这个看起来是这四条里面最简单的。当SF^OF
为1时(此条指令代表的是aSF^OF为1:
a) SF = 1 OF = 0
,此时OF = 0
即没有发生溢出,那么结果t就是正常结果。SF = 1
即结果t是负数,即a-b<0即a b) SF = 0 OF = 1
,此时OF = 1
即发生了溢出,且SF = 0
说明结果t为非负数,所以很明显这里是发生的负溢出,所以溢出结果为非负数。a-b>=0这里负溢出,所以两个部分都为负,a为负,-b为负,所以b为正,既然a为负,b为正,那儿必有a
2)分析setle
。既然SF^OF = 1
代表小于且ZF = 1
代表等于,那么(SF^OF) | ZF = 1
就代表小于或者等于。
3)分析setge
。既然SF^OF = 1
代表小于,那么整体取反后,~(SF^OF) = 1
,就代表大于等于。(小于的反面就是大于等于)
4)分析setg
。既然(SF^OF) | ZF = 1
就代表小于等于,那么整体取反后,~(SF^OF) & ~ZF = 1
(注意取反后或符号变为与符号),就代表大于。
分析无符号数的4种指令。
分析过程跟上面一样,但这里书上没有解释清楚CF进位标志的其他作用,导致这里如果只看书是看不懂的。
CF进位标志的作用:
1.当两个数相加时,若最高位向上形成进位,则CF=1;
2.当两个数相减时,若最高位向上形成借位,则CF=1;
3.当两个无符号数相乘时,若乘积的高一半为0,则CF=0;
4.当两个带符号数相乘时,若乘积的高一半是低一半的符号扩展,则CF=0.
以上来自网络。这里用到了CF进位标志的第2个作用,既然相减时最高位都借位了,所以a-b<0即a 跳转指令编码一般是PC相对的,即目标指令的地址,是由跳转指令的下一条指令的地址再加上一个地址偏移量得到的。 下面再来验证跳转指令的目标指令地址是如何计算: 如果c语句是 将两个操作数进行按位AND,设结果是TEMP 因为 同时这里也说明了,用test指令来测试一个寄存器与0的关系时(大于等于小于)(而且这里特指两个操作数是同一个的情况),小于和等于必须放在一起,大于单独放。即使用3.13
每个答案的第一条指令确定了数据类型大小。
第二条指令确定了是否有无符号,具体看答案。
具体分析上面的set指令表格吧:
从sete到setne
,可能是无符号数,补码数,和指针(如果指针,还得看大小是否为指针大小)。
从sets到setns
,补码数(根据答案讲解推断的,如有错误请见谅)。
从setg到setle
,补码数。
从seta到setbe
,无符号数。跳转指令编码
地址偏移量是,跳转指令的机器编码的最高的那个字节,所代表的补码数。
每行代表一个指令的机器代码,比如第一行,代表的是这条mov指令,这条指令占了3个字节,分别是0,1,2这三个字节,所以这条mov指令的地址为0x0,而下一条jmp指令的地址为0x3。(地址是指指令的开始地址)
看上面机器代码的第2行,是jmp跳转指令,它的最高单字节为0x03,它所代表的补码数为3,而下一条指令的地址为0x5,所以目标指令地址=0x5+0x3=0x8。
同理,看第5行的jp跳转指令,它的最高单字节为0xf8,它所代表的补码数为-8,而下一条指令的地址为0xd,所以目标指令地址=0xd-8=0xd-0x8=0x5。3.15
只看D选项。
先看字节排序,从左到右是,低字节地址到高字节地址。
再看有效位排序,因为是小端法字节顺序,即高有效位在高字节地址。所以,从左到右是,低有效位到高有效位。
上一章说了,一般取的是高有效位的,而这里是4个字节而不是1个字节,所以偏移量为0xffffff73
即1 0111 0011
(利用补码快速计算)所代表的补码数-141
。cmp指令操作数顺序
if(x < y)
,且x in %rdi , y in %rsi
,那么汇编里面执行的比较指令为cmp %rsi, %rdi
。
即比较符号左边的数放在cmp右边的操作数,右边的数放在cmp左边的操作数。所以可以通过c语句和汇编语句互相确认操作数的左右。
再配合跳转指令的话,if(x < y)
的语句块就使用jl
(代表小于),else
的语句块就使用jge
(代表大于等于)。3.16
testq %rsi, %rsi
用来检测p指针是否为空指针,且如果为空指针,那么将ZF零标志置为1。je .L1
,如果ZF=1,那么跳转到L1,然后直接返回。从c语句来看,因为p为空指针了,条件肯定不成立,然后跳转到L1,然后直接空操作(因为rep)后结束。cmpq %rdi, (%rsi)
,这句注意,由于本来c语句是a > *p
,所以这里本应是cmpq (%rsi), %rdi
,但实际上汇编这里也可以交换位置,那么这里实际是*p < a
。接着分析,如果*p < a
这个条件为假即*p >= a
成立,那么就跳转到L1,所以这里用的是jge
跳转(greater and equal)。3.21
原题不放了,其他地方都好懂,只是testq和jle配合使用感觉很奇怪,但书中并没有详细说明test指令到底可能改变哪些条件码。详情请看TEST指令——百度百科。
SF = 将TEMP的最高位赋给SF标志位,例如结果最高位是1,SF就是1
如果TEMP是0,ZF位置1;如果TEMP不是0,ZF位置0
OF位置0jle
指令的跳转条件是(SF^OF)|ZF
,那么就重点关注TEST指令对这三个条件码的变化吧。且testq %rsi, %rsi
这里用到的是自测。
所以现在需要验证,当y小于等于0,能使得跳转条件(SF^OF)|ZF
为1:
1)当y=0.(0^0)|1 = 1
,验证成功。
2)当y<0.(1^0)|0 = 1
,验证成功。
3)当y>0.(0^0)|0 = 0
,顺便验证第三种条件,发现小于等于的反面情况会使得跳转条件为0,反向验证成功。
所以当y小于等于0时,会执行jle
指令然后进行跳转。jle
和jg
。