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. 两个逻辑门的输出不能连接到一起,否则它们可能会使线上的信号矛盾,因此可能会得到一个不合法的电压或故障。比如1个0V和1个1V接到一起,会不会出来个0.5V,又或者类似于正负极相接,直接短路了呢。
  2. 组合的电路必须是无环的。也就是说输出不能再当做输入,否则会使这个函数产生歧义。这个道理很简单,比如数学上来说,如果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安装

  • 下载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能实现的功能:

  1. 通过自带的bbswitch组件,自动关闭独立显卡,节省电力,降低发热量。

  2. 通过bumblebee-nvidia组件,能安装nvidia官方驱动,并用optirun方式用独显运行显示需求较高的程序。

  3. 支持NVIDIA的CUDA程序加速。(我没验证过,不知道有没有效!)

配置方式超简单,直接apt-get install ,安装完重启立即生效,简单方便

  • 步骤
  1. 打开终端,输入:

sudo add-apt-repository ppa:bumblebee/stable

  1. 然后输入:

sudo apt-get update

  1. 开始安装。

在终端输入:

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模拟器

参考资料

原文地址:https://www.cnblogs.com/nostalgia-/p/5991294.html