这是一篇基调凄凉的文章,因为笔者半期考试没上我们转专业班班平。
准确来说,整个半期考试都考得很差,是时候反思并且改进学习方法了。
原因一方面是对条件码极度不熟悉,这个我觉得并不重要的东西反而每个题都在考,一方面是感觉知识还没有融汇,另一方面是老师出了点超纲的数组题(我菜是原罪...)。这篇水文的主要目的是根据考试犯错的题,排一下知识盲点解决一下上半学期遗留的问题。最重要的是知识还没融会贯通,这是原罪。还有想吐槽一下考试用ppt呈现题目但是不发卷子,这个就非常恶心了。这篇文章旨在就一些错误进行反思和总结,个人向而已:
零、关于标志位和整数加减法的东西:
这就很难受了,我没有怎么看第二章的东西,并且标志位也没记住...老师不挂我挂谁?
CF:进位标志,最近的操作让最高位产生了进位,可用来检查无符号数的溢出。
OF:溢出标志,最近的操作让一个补码溢出了,要么是正溢出,要么是负溢出。
ZF:得零标志,最近的操作的结果得零,则ZF=1;
SF:是负数(符号位signal为1)标志,最近的操作得结果得到一个负数。
楼下是笔者找的某一位博主总结的一幅图,我觉得很ok的:
对于整数加法:
1.x与y都是无符号数,w位的(一个w位的无符号数,它最大时11111...1(w个1),值是2^w -1),那么0<=x,y<=2^w -1,那么如果x+y没有超过2^w,那么该是多少是多少,如果溢出了,那么我们就取mod 2^w.
2.x,y都是有符号数,w位的(一个w位的有符号数,它最大是0111.....1(w-1个1),值是2^(w-1) -1),最小是10000...0(w-1个0),值是-2^(w-1) ),那么就有正溢出和负溢出了。
一、浮点数表示
y=0xd3e4c000的十进制数。(题中说了y是浮点数,我...我没看到,虽然可能即使看到了,我考试的时候也忘了)
我们转化为二进制串,y=1*101 0011 1* 110 0100 1100 0000 0000 0000.【*表示字段的分类】对于32位4字节的float型,第一位是符号位,1表示是负数,然后我们计算阶码部分,E=e-Bias,BIas=2^(阶码位数-1)-1,一般的float型是1,8,23这种字段结构,所以float的Bias是127;double型是1,11,52这种字段结构,其偏置Bias=1023.所以本题中,阶码的值E=e-BIas=(101 0011 1)2 -127=(40)decimal。然后我们计算尾数M,M一般等于1+f(隐含1开头),如果阶码全零则M=f。所以本题答案是 V=(-1)* 2^40 * (1+1/2+1/4+1/32+...)。
二、一道综合题:
1.add是自增运算,考试的时候忘记加自身了
首先,%rdi+%rcx=0x1020,再加便宜0x8,得到地址0x1028,这个地址中的值是0xca50,然后我们进行值与值之间的加法运算,将值0xca50加上值0xaa,就得到了0xcafa。
2.testq %rdx %rdx,%rdx内的值是0xaa不等于zero,所以ZF=0。然后cmovne也因为(不相等/非零),所以要送数。
3.%rdi和%rsi加起来的地址加偏置6得到0x1009,因为条件码ZF=0,我们从中取得按小端(低数位存在前面,高数位存在后面的规则)取出8个字节(%rax),0x1008--89,0x1009--67,0x100a--05,0x100b--00,0x100c--00,0x100d--00,0x100e--00,0x100f--00,0x1010--22,我们取出八个内存64位,分别是0x1009--67,0x100a--05,0x100b--00,0x100c--00,0x100d--00,0x100e--00,0x100f--00,0x1010--22,那么%rax的值就是0x2200000000000567。
4.我们从%esi中自减立即数Imm=4,得到-1,由于%esi是四字节32位,十六进制数四位为一个数位,所以一共会有8位(16进制),而-1用十六进制表示,就是0xffffffff,这是因为0xffffffff=-1*最高权+1*次高权+1*次次高权+....= - 1.(简单的等比数列)。
5.我们将%ebx内的值0xc,即1100,sall,左移动29位,那么我们从第一位到第32位中,是第三位移到32位的(32-3=29),所以第三十二位(最高的标志位)得到1,代表“是负数”,那么SF=1,命题为真。(考试的时候,我数错了!!!)
6.当移动后,我们得到的是0x1000....此处省略一系列个0,表示的是=-1*最高位位权=(可以是)INT_MIN,然后我们进行cmpl $2 %ebx操作,在int-min基础上减去2,又回到一个正数,这个正数是int-max-1,那么发生了负溢出,我们置OF=1.然后因为这种compare操作只是比较不改变,所以%ebx该是多少是多少不改变。
7、这个题体现了计算机能够分段送数的特性,所以我们将末尾16位两字节送入%ax中,%rax其余位不变,但是注意到%rax在前面的运算中已经改变过值了,所以只用把低16位改变成0x0088,前面不变就行。
8.js表示“是负数就跳转”,由于我们最后得到(相减来判断)一个正数,所以后者“大”,所以不是负数,所以不跳转。
另外,加括号就是取地址,leaq我们单独说。
leaq:加载有效地址,看似是从内存里面读数据到寄存器中,其实压根就没有引用内存,根本就与有效地址计算无关,其本质是mov指令的变形,对source操作后送入destination之中而已。
三、分析一个汇编,填空:
fabe:
movl $0,%eax
jmp .L2
.L5 movslq %eax,%r8
leaq (%rdi,%r8,4),%rdx
movl (%rdx),%ecx
cmpl %ecx,%eax
jne .L3
addl %eax,%ecx
movl %ecx,(%rdx)
ret
.L3 leaq 4(%rdi,%r8,4),%r8
movl (%r8),%r9d
movl %r9d,(%rdx)
movl %ecx,(%r8)
addl $1,%eax
.L2 cmpl %esi,%eax
jl .L5
movl $-1,%eax
ret
//源码:
int fabe(int *a,int m)
{
int i,temp;
for(i=0;i<m;i++)
{
temp=a[i];
if(i==temp)
{
?; //temp+=i;
return ?; //return i; gcc调用约定%eax习惯上作为返回值
}
else
{
?;//a【i】=a【i+1】;
?;//a【i+1】=temp;
}
}
return ?; //-1
}
最后,想给自己说,这套题回头看如此简单,考的不好不是一件羞耻的事情,这是暴露自己问题的机会,后面一个月要加油了,争取期末总评还有90+!
期末考完了,估计可能上不了90了,我有些哽咽。