20145211《信息安全系统设计基础》第六周学习总结——赏心乐事
20145211《信息安全系统设计基础》第六周学习总结
教材学习内容总结
Y86
Y86指令体系结构
- Y86是一个指令体系结构(ISA),它是计算机系统这本书的作者YY出的指令集。目的是为了让我们更加清晰的了解ISA。
- 我们的目的是为了了解CPU处理指令的流程以及它的工作原理,学习它的思想,这对你以后的技术之路说不定会有一些启发。很多时候,这种启发是很重要并且难得的,非神人不能达到。
- 对于Y86,LZ也没有太多可介绍的,它就是一个ISA的例子,让各位通过它来了解ISA的设计。这一章的内容比较轻松,因为我们已经在第三章了解过X86的汇编指令,更多精彩内容还是要在后面再展现出来~
看的见的手
- 计算机是一个神秘的家伙,它的很多秘密我们都看不到,不过有了ISA的帮忙,我们就可以了解到很多计算机的秘密。比如hzy现在写博文的时候,CPU到底在干什么呢?
- 理论上来讲,我们在编写一个程序的时候,我们是可以知道CPU的状态的。因为在你观察程序的汇编指令时,你可以知道当程序执行到某个地方,寄存器、存储器以及条件码寄存器等等的状态是如何的。说到底,无论是寄存器,存储器还是条件码寄存器等等,都是汇编指令可以访问的处理器状态。在设计和实现一个处理器的时候,只要我们能保证机器级程序(比如汇编程序)可以正常的访问程序猿可见状态(比如寄存器、存储器),那么就不太需要非得按照ISA真正的方式来表示我们的处理器状态。
- 对于Y86来说,它的程序猿可见状态就是这几种:寄存器、存储器、条件码、PC、程序状态。
- 在Y86当中,寄存器依旧是8个,每一个寄存器可以存储一个字,也就是一个32位二进制。条件码是一个一位二进制的寄存器,保存着最近的算术或逻辑运算所造成的影响的信息。PC则是程序计数器,记录当前正在执行的指令的地址。
- 存储器则是一个很大的字节数组,Y86的程序可以使用虚拟地址(类似于数组的下标)来访问存储器,硬件和操作系统会将虚拟地址翻译为实际的地址。最后一个程序状态(stat),它则代表着程序的运行情况。
- 这些都是可见的状态,或者说机器级程序可访问的CPU状态,我们在设计和实现一个处理器的时候,就是设计一系列指令去操作这些状态。
Y86指令集
- 接下来我们就看看Y86的指令集,我就直接上图了,这些指令其实都是从X86的指令集YY而来。
-上面的指令相信大家都不会太陌生,我这里就不仔细的解释了,下面我们只简单的把每个指令的作用过一遍。
-
halt:这个指令将会终止指令的执行。
-
nop:这是一个占位指令,它不做任何事情,后续为了实现流水线,它有一定的作用。
-
xxmovl:这是一系列的数据传送指令,其中r代表寄存器,m代表存储器,i代表立即数。比如rrmovl指令,则代表将一个寄存器的值,赋给另外一个寄存器。
-
opl:操作指令,比如加法,减法等等。
-
jxx:条件跳转指令,根据后面的条件进行跳转。
-
cmovxx:条件传送指令,后面的xx代表的是条件。特别的是,条件传送只发生在两个寄存器之间,不会将数据传送到存储器。
-
call与ret:方法的调用和返回指令。一个将返回地址入栈,并跳到目标地址。一个将返回地址入PC,并跳到返回地址。
-
push与pop:入栈和出栈操作。
指令编码
- 在上图的右边,是指令所占的字节数或者说编码。一般两个寄存器占用一个字节,存储器则占用四个字节,指令的编码和功能占用一个字节。因此可以看到,比如rrmovl指令,它的字节长度是2,其中第一个字节代表了指令rrmovl,第二个字节代表了两个寄存器。
- 对于opl、jxx、cmovxx指令来说,都有一个fn标识,占用4个二进制位(半个字节)。这个便是指令的功能部分,这个是由于它们的指令编码一样,但功能有所不同所造成的。比如对于opl,就有加、减、与、异或等操作,那么它们的指令编码第一个字节就分别为十六进制的60、61、62、63。
- 对于寄存器的表示,是使用4个二进制位表示的,这是一个ID标识。所有的寄存器可以看做是一个寄存器文件,其中的ID标识就类似于它们的地址。对于一些只需要一个寄存器的指令来说,另一个寄存器标识位使用0xF表示。
- 还有的指令需要一个字的常数,比如irmovl指令,call指令等等。这种指令,将把常数放在最后的四个字节当中,顺序按照大端法或小端法表示(与机器和OS有关)。对于call指令来说,这四个字节就是一个地址,这个地址就是绝对地址,指向了存储器当中的某一个位置,这个位置存储着代码。采用绝对地址是为了描述简单,真实当中,是采取的基于PC的相对地址。
Y86异常
-
对于Y86来说,程序猿可见的状态中就有stat状态码,它标识了程序执行的状态。Y86需要有能力根据stat去做一些处理。不过为了简单起见,这里除了正常执行之外,都将停止指令的执行。真实当中,会有专门的异常处理程序。
-
Y86有四种不同的状态码,AOK(正常)、HLT(执行halt指令)、ADR(非法地址)和INS(非法指令)。
Y86程序
- 书中给出了一个示例程序,来说明X86和Y86的区别,这里LZ就不详细分析这些汇编指令了,这种事情在第三章已经做的很多了,各位猿友可以私底下自己分析一下。其实两者是非常相似的,毕竟Y86就是根据X86的结构YY出来的。区别就在于,有的时候Y86需要两条指令来达到X86一条指令就可以达成的目的。
- 比如对于X86指令中的 addl $4,%ecx 这样的指令,由于Y86当中的addl指令中不包含立即数,所以Y86需要先将立即数存入寄存器,即使用irmovl指令,然后再使用addl来处理加法运算。
- 总的来说,Y86就是一个X86的缩减版,它的目的是以简单的结构实现一个处理器,帮助我们了解处理器的设计和实现。有兴趣的猿友可以去观摩一下Y86程序生成的汇编代码,并进行逐一的分析,实际上,这与X86是十分类似的。
HCL
前期基础
- 计算机归根结底是在和0、1打交道,那么到底0和1是如何被计算机记住的?其是计算机通过电压来记录0和1。
- 逻辑门是数字电路的基本计算元素,也可以看做是物理结构与逻辑结构的映射,它们实际上是由晶体管组成的。逻辑门接受信号的输入,并根据信号产生一定的输出,而输出则是输入的布尔函数,也就是说,输出只能是0或者1。and和or都是2个输入,而not为1个输入。
- 举个例子,比如对于and门来说,它接受2个输入,如果2个输入都是高位电压,则输出的为高位电压,也就是输出为1。否则的话,都是输出低位电压,也就是输出为0。这些就是建立在刚才1V为1,0V为0的基础之上的。
高级设计
- 一个逻辑门可以计算1位,如果我们弄来32个逻辑门,不就可以计算32位了吗?组合的电路需要遵循以下两个原则。
- 两个逻辑门的输出不能连接到一起,否则它们可能会使线上的信号矛盾,因此可能会得到一个不合法的电压或故障。比如1个0V和1个1V接到一起,会不会出来个0.5V,又或者类似于正负极相接,直接短路了呢。
- 组合的电路必须是无环的。也就是说输出不能再当做输入,否则会使这个函数产生歧义。这个道理很简单,比如数学上来说,如果c=a+b。我们这里可以把c看做输出,a和b看做输入。如果a又等于c了,那么是不是b就等于0了呢?当然不是,因为a此时其实是a+b,第二轮的c又会等于a+2b,同理,第三轮的c又会等于a+3b。那么到底c=a+b还是c=a+2b还是c=a+3b?遵循以上原则,我们就可以随意组装电路了。
- 在书中对HCL表达式与C语言的表达式做了区分,有以下三点。
1. 逻辑门是持续输出的,但C语言表达式是执行到的时候才会求值。这个区别可以把逻辑门当成一个电路来看,电路是不能断电的,电流会一直存在。
2. C语言中输入可以是任意整数,而HCL只能是1和0。这点比较好理解。
3. 对于a && b这个符号来说,C语言中的规定是如果前者为假,则后者不会再计算。而HCL当中没有这种说法。
按位计算
-
所有的设计都是针对1位进行操作的。那么如何才能真正操作多个位呢,比如平时常用的32位或者64位。道理很简单,就是多个1位操作一起进行,例如下面这个图。
-
这个图当中每个位相等的判断都是上面所提到的两个not门,两个and门和一个or门组成的组合电路。它们并列的一起进行,最终再通过一个and门,就完成了判断两个32位的数字是否相等的操作。也就是表达式A == B,值得注意的是,这里的A和B都是32位的。
-
还有一种类似于C语言中switch语句的表达式,就是如下形式。
int Out = {
s:A;
1:B;
}; -
它代表的意思就是如果s为1,则输出A,否则输出B,同样,这里的A和B都是32位的。那么使用电路如何表达呢?其实就是上次的复用电路的32位版本。如下图。
-
可以看到,s的not值是被复用的,否则的话,这里需要32个not门。值得一提的是,HCL中条件选择表达式中的条件是不需要互斥的,只是按照优先顺序依次选取,这与C语言中的switch是不同的。
-
最后一种HCL表达式,是集合的形式。它表示需要拿一个输入信号与某些值做匹配。
存储器和时钟
- 上面我们介绍的都是组合电路,它们的作用是根据输入来产生一个值。但是刚才也说过,组合电路是一直持续输出的,因此它无法保持一个状态不变。但我们的计算机是需要存储数据的,因此就需要能保存状态的存储设备。存储设备则是由一个时钟控制,时钟就像一个开关一样,它控制着存储设备什么时候更新设备里的值。
- 常用的存储设备一般有两种。
1. 时钟寄存器:存储单个位或者单个字。时钟信号来控制寄存器是否要加载输入的值。
2. 随即访问存储器:存储多个字。用地址来选择该读、写哪个字。
时钟寄存器的典型应用是PC、条件码寄存器以及程序状态。它们都有明确的输入,这意味着它们的值其实是某几个值的一个函数,比如条件码寄存器的输入主要就是逻辑计算单元的值,因此条件码寄存器的值就可以看做是逻辑计算单元的函数。
时钟寄存器一般是根据时钟信号来更新状态的,而时钟信号就像一个表一样,比如每到12点,寄存器的值就更新一下。
随即访问存储器最典型的例子就是我们的寄存器文件(也就是8个程序寄存器)和随即访问存储器(也就是我们常说的内存)。它们没有明确的输入值,因此不存在函数关系。不论是寄存器文件还是随即访问存储器,都有读和写两种操作,而对于时钟寄存器来说,是无所谓读和写的,因为它只会根据输入的变化改变输出的值,是可以直接连接到电路上去的。
练习题
-
练习题4.1
解答:
irmovl $15,%ebx ##30f30f000000
rrmovl %ebx,%ecx ##2031
loop:
rmmovl %ecx,-3(%ebx) ##4013fdffff
addl %ebx,%ecx ##6031
jmp loop -
练习题4.2
确定下列每一个字节序列所编码的Y86指令序列。如果有不合法字节,指出其位置。
A.
0x100:30f3fcffffff ##irmovl $-4,%ebx
0x106:406300080000 ##rmmovl %esi,0x800(%ebx)
0x10c:00 ##halt
B.
0x200:a06f ##pushl %esi
0x202:8008020000 ##call proc
0x207:00 ##halt
0x208:
0x208:30f30a000000 ##irmovl $10,%ebx
0x20e:90 ##ret
C.
0x300:505407000000 ##mrmovl 0x7(%esp),%ebp
0x306:10##nop
0x307:f0##非法
0x308:b01f ##popl %ecx
- 练习题4.5
解答:
int Sum(int Start,int Count)
{
int sum = 0;
while(Count)
{
sum+=Start;
Start++;
Count--;
}
return sum;
loop:
mrmovl (%ecx),%esi get x = *Start
irmovl $0,%edi 0
subl %esi,%edi -x
cmovg %edi,%esi if -x > 0 then x = -x
addl %esi,%eax add x to sum
irmovl $4,%ebx
addl %ebx,%ecx Start++
irmovl $-1,%ebx
addl %ebx,%edx Count--
jne loop Stop when 0
问题解决
Y86安装
- 安装的步骤主要参考了20145218的博客:http://www.cnblogs.com/senlinmilelu/p/5985966.html#3538763
- 安装bison和flex词法分析工具,在终端中输入sudo apt-get install bison flex
-
下载sim解压:wget http://labfile.oss.aliyuncs.com/courses/413/sim.tar
-
图形界面须要安装Tcl/Tk,在终端中输入sudo apt-get install tcl8.5-dev tk8.5-dev tcl8.5 tk8.5
-
在解压后的sim文件夹中找到makefile文件,作如下改动并保存
GUIMODE=-DHAS_GUI // 将#去掉
TKLIBS=-L/usr/lib/ -ltk8.5 -ltcl8.5 // 加上8.5
TKINC=-I /usr/include/tcl8.5 //将isystem改为大写的I,在最后加上tcl8.5
- 编译 在sim文件夹下右键选择在终端中打开,输入make clean;make
(make clean的主要作用就是把yo的文件删除)
- make all之后使用cat查看编译好的asuml.yo文件。
ubuntu耗电的问题
-
现在的笔记本大都使用NVIDIA的Optimus双显卡,而Ubuntu本身并不支持Optimus双显卡切换技术,所以,使用了这种双显卡技术的笔记本安装了Ubuntu之后,使用过程中,集显独显都是处于开启状态,发热量和耗电量居高不下。某些机型可以通过BIOS关闭独显,但是总免不了有需要使用独显的时候。有市场就有需求,于是bumblebee 3便出现了
-
bumblebee3能实现的功能:
-
通过自带的bbswitch组件,自动关闭独立显卡,节省电力,降低发热量。
-
通过bumblebee-nvidia组件,能安装nvidia官方驱动,并用optirun方式用独显运行显示需求较高的程序。
-
支持NVIDIA的CUDA程序加速。(我没验证过,不知道有没有效!)
配置方式超简单,直接apt-get install ,安装完重启立即生效,简单方便
- 步骤
- 打开终端,输入:
sudo add-apt-repository ppa:bumblebee/stable
- 然后输入:
sudo apt-get update
- 开始安装。
在终端输入:
sudo apt-get install bumblebee
(该命令自动安**umblebee 3)
sudo apt-get install bumblebee-nvidia
(该命令安装NVIDIA官方驱动)
安装完成,重启
- 装了bumblebee 3后,笔记本右侧散热风扇出风口的温度立即下降,效果立竿见影
磁盘不共享的问题
- 刚开始我非常方便的在linux下访问windows里的盘区的时候,有一天,他突然出现了这个error
看看报错:Please resume and shutdown Windows fully (no hibernation or fast restarting)
译:请重启电脑把windows 完全关闭 (没有休眠或者快速启动)这种情况下,是没有办法设置读写权限的只能是-ro (read only只读)只能在/etc/fstab 里设置:UUID=1E7E5FE17E5FAFEF /media/222 ntfs ro,defaults,auto,nodev,nosuid,user,force 0 0
注意:只能是ro ,如果是rw启动会报错!
通过$ ls -all /dev/disk/by-uuid/ 可以查到UUID
注意:这样挂载不能对挂载盘的修改!!read only!!!
如果你的win8 没有设置快速启动或者没有什么问题的话,应该可以吧ro改为rw(读写)的
后来我了解到,windows下为了快速启动,内核采用了“休眠”的模式,启动时就是混合启动,所以速度很快,一般8秒左右;于是只要在win10下,命令行彻底关机就行了:shutdown -s -t 1
心得体会
- 总的来说,本章的难度并不高。先是简单的介绍了一个类X86的指令集结构,接着让我们了解了具体的设计是如何进行的,以及如何使用硬件控制语言HCL。后面的内容相对来说会比较难理解,我在读的时候也是有点一知半解,尽管现在已经基本摸清了套路。这些硬件,就是Y86处理器需要使用的。比如组合电路,存储器。到本章最后的时候,已经非常接近我们的编程领域了,可以看到有寄存器和内存的出现。但要注意的是,这里的寄存器文件并不等于寄存器,随即访问存储器也不等于内存。
- 就我本身来讲,读这本书的时候,最大的感受就是,每一章刚开始读的时候都非常枯燥无味,但每当读了几节以后,就有种豁然开朗的感觉,这种感觉相信你一定也非常喜欢。因为如果你慢慢的进入了这个世界,你会觉得这是一件非常有意思的事情。
本周代码托管
学习进度条
代码行数(新增/累积) | 博客量(新增/累积) | 学习时间(新增/累积) | 重要成长 | |
---|---|---|---|---|
目标 | 5000行 | 30篇 | 400小时 | |
第一周 | 120/200 | 1/2 | 16/16 | 学习Linux核心命令 |
第二周 | 100/200 | 1/3 | 30/46 | 学习vim,gcc以及gdb的基本操作 |
第三周 | 30/230 | 1/4 | 15/61 | 对信息的表示和处理有更深入的理解 |
第四周 | 30/260 | 1/5 | 22/83 | 双系统的探索 |
第五周 | 130/390 | 1/6 | 25/108 | 汇编的深入学习 |
第六周 | 60/450 | 1/7 | 25/133 | 熟悉了Y86模拟器 |