《深入理解计算机系统》练习题3.13-3.16 set指令 跳转指令编码

set指令访问条件码

在这里插入图片描述
在这里插入图片描述
SET指令根据条件码或者条件码的组合来将一个字节设置为0或1(所以如果set指令后面跟的是寄存器,那么必须是单字节的寄存器)。
在经过了比较指令a<b,即有t=a-b后,就会根据运算的过程和结果设置条件码。注意不管是无符号数还是补码数,t一定是发生溢出后的截断结果(如果有发生溢出)。
分析有符号数的4种指令。

1)分析setl。因为这个看起来是这四条里面最简单的。当SF^OF为1时(此条指令代表的是a<b,即为1时有a<b),会将D设置为1,否则设置为0。有两种情况SF^OF为1:
a) SF = 1 OF = 0,此时OF = 0即没有发生溢出,那么结果t就是正常结果。SF = 1即结果t是负数,即a-b<0即a<b。符合情况。
b) SF = 0 OF = 1,此时OF = 1即发生了溢出,且SF = 0说明结果t为非负数,所以很明显这里是发生的负溢出,所以溢出结果为非负数。a-b>=0这里负溢出,所以两个部分都为负,a为负,-b为负,所以b为正,既然a为负,b为正,那儿必有a<b。符合情况。

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<b.

3.13

在这里插入图片描述
每个答案的第一条指令确定了数据类型大小。
第二条指令确定了是否有无符号,具体看答案。
具体分析上面的set指令表格吧:
从sete到setne,可能是无符号数,补码数,和指针(如果指针,还得看大小是否为指针大小)。
从sets到setns,补码数(根据答案讲解推断的,如有错误请见谅)。
从setg到setle,补码数。
从seta到setbe,无符号数。

跳转指令编码

跳转指令编码一般是PC相对的,即目标指令的地址,是由跳转指令的下一条指令的地址再加上一个地址偏移量得到的。
地址偏移量是,跳转指令的机器编码的最高的那个字节,所代表的补码数。
在这里插入图片描述
每行代表一个指令的机器代码,比如第一行,代表的是这条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个字节,所以偏移量为0xffffff731 0111 0011(利用补码快速计算)所代表的补码数-141

cmp指令操作数顺序

如果c语句是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指令——百度百科

将两个操作数进行按位AND,设结果是TEMP
SF = 将TEMP的最高位赋给SF标志位,例如结果最高位是1,SF就是1
如果TEMP是0,ZF位置1;如果TEMP不是0,ZF位置0
OF位置0

因为jle指令的跳转条件是(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指令然后进行跳转。

同时这里也说明了,用test指令来测试一个寄存器与0的关系时(大于等于小于)(而且这里特指两个操作数是同一个的情况),小于和等于必须放在一起,大于单独放。即使用jlejg

posted @ 2018-11-23 00:23  allMayMight  阅读(478)  评论(0编辑  收藏  举报