20145215《信息安全系统设计基础》第六周学习总结
20145215《信息安全系统设计基础》第六周学习总结
教材学习内容总结
Y86指令集体系结构
- 内容:定义一个指令集体系结构,包括定义各种状态元素、指令集和它们的编码、一组编程规范和异常事件处理。
程序员可见状态
- Y86程序中的每条指令都会读取或修改处理器状态的某些部分。
- Y86具体包括:8个程序寄存器、3个条件码ZF\SF\OF、程序计数器(PC)。
- Y86用虚拟地址引用存储器位置。 程序状态的最后一个部分是状态码Stat,它表明程序执行的总体状态。
Y86指令
-
IA32指令集的一个子集,只包括四字节整数操作。寻址方式比较少,操作也比较少。
-
指令编码长度从1个字节到6个字节不等,一条指令含有一个单字节的指令指示符,可能含有一个单字节的寄存器指示符,还可能含有一个四字节的常数字。字段fn指明是某个整数操作(OPL)、数据移动条件(cmovXX)或是分支条件(jXX),所有数值都用十六进制表示
-
call指令将返回地址入栈,然后跳到目的地址。ret指令从这样的过程调用中返回。
-
pushl和popl指令实现了入栈和出栈。
-
halt指令停止指令的执行。对于Y86来说,执行halt指令会导致处理器停止,并将状态码设置为HLT。
指令编码
- 每条指令的第一个字节表明指令的类型。这个字节分为两个部分,每部分4位:高4位是代码部分,低4位是功能部分。功能值只有在一组相关指令共用一个代码时才有用。
- 8个程序寄存器中每个都有相应的0~7的寄存器标识符,程序寄存器存在一个寄存器文件中,这个寄存器文件就是一个小的、以寄存器ID作为地址的随机访问存储器。当需要指明不应访问任何寄存器时,用ID值0xF表示。
数字 | 寄存器名字 |
---|---|
0 | %eax |
1 | %ecx |
2 | %edx |
3 | %ebx |
4 | %esp |
5 | %ebp |
6 | %esi |
7 | %edi |
F | 无寄存器 |
- 有的指令没有寄存器操作数(分支指令和call指令),就没有寄存器指示符字节;只需要一个寄存器操作数的指令(irmovl、pushl、popl),将另一个寄存器指示符设为0xF。
- 指令集的一个重要性质:字节编码必须有唯一的解释。
Y86异常
- Y86状态码(在我们的设计中,任何AOK以外的代码都会使处理器停止)
值 | 名字 | 含义 |
---|---|---|
1 | AOK | 正常操作 |
2 | HLT | 处理器执行halt指令 |
3 | ADR | 遇到非法地址 |
4 | INS | 遇到非法指令 |
- 出现异常时Y86处理器停止运行指令,可以调用一个异常处理程序使其更完整。
Y86程序
- Y86代码与IA32代码的主要区别:
- Y86可能需要多条指令来执行一条IA32指令所完成的功能。
- Y86没有伸缩寻址模式。
- 命令指明应该将代码或数据放在什么位置,以及如何对齐。这个程序详细说明了栈的放置、数据初始化、程序初始化和程序结束等问题。
- 以“.”开头的词是汇编命令,他们告诉汇编器调整地址,以便在那儿产生代码或插入一些数据。
- 创建Y86代码的唯一工具是汇编器。
- 指令集模拟器YIS:
- 目的:模拟Y86机器代码程序的执行,而不用试图去模拟任何具体处理器实现的行为。
- 有助于在实际硬件可用之前调试程序,也有助于检查模拟硬件或者在硬件上运行程序的结果。
一些Y86指令的详情
- 大多数Y86指令是以一种直接的方式修改程序状态的。
- 执行pushl和popl指令时,处理器的行为是不确定的,因为要入栈的寄存器会被同一条指令修改。通常有两种约定:
- 压入/弹出%esp的原始值
- 压入/弹出%esp-/+4后的值
逻辑设计和硬件控制语言HCL
- 要实现一个数字系统需要三个主要的组成部分:
- 计算对位进行操作的函数的组合逻辑
- 存储位的存储器元素
- 控制存储器元素更新的时钟信号
逻辑门
- 逻辑门产生的输出,等于它们输入位值的某个布尔函数。逻辑门只对单个位的数进行操作,而不是整个字。
- 逻辑门总是活动的,一旦一个门的输入变化,在短时间内,输出就会跟着变化。
组合电路和HCL布尔表达式
- 组合电路:将很多的逻辑门组合成一个网,能构建计算块。
- 多路复用:根据输入控制信号的值,从一组不同的数据信号中选出一个。
- 构建这些网有两条限制:(1)两个或多个逻辑门的输出不能连接在一起(2)这个网必须是无环的。
- HCL表达式和C语言中逻辑表达式的区别:
- 组合逻辑电路的输出会持续地响应输入的变化;C表达式只有在程序执行过程中被遇到时才会求值。
- C的逻辑表达式允许参数是任意整数,0表示FLASE,其他任何值都表示TRUE;逻辑门只对位值0和1进行操作。
- C的逻辑表达式可能只被部分求值;组合逻辑没有部分求值的规则,逻辑门只是简单地响应输入的变化。
字级的组合电路和HCL整数表达式
- 执行字级计算的组合电力根据输入字的各个为,用逻辑门来计算输出字的各个位。
- 用中等粗度的线来表示携带字的每个位的线路,用虚线来表示布尔信号结果。
- 在HCL中,多路复用函数用情况表达式来描述。
- 算术/逻辑单元是一种很重要的组合电路。
集合关系
- 判断集合关系的通用格式是:
iexpr in {iexpr1,iexpr2,……,iexprk}
存储器和时钟
- 存储设备都是由同一个时钟控制,两类存储器设备包括:
- 时钟寄存器(寄存器):储存单个位或字,用时钟信号控制寄存器加载输入值。
- 随机访问储存器(储存器):储存多个字,用地址选择该读/写哪个字。
- 硬件和机器级编程中的寄存器有细微差别,分为称为“硬件寄存器”和“程序寄存器”。
- Y86处理器会用时钟寄存器保存程序计数器PC,条件代码CC和程序状态Stat。
- 处理器有一个随机访问存储器来存储程序数据。
- 处理器还包括另外一个只读存储器,用来读指令。
- 在大多数实际系统中,这两个存储器被合并为一个具有双端口的存储器:一个用来读指令,一个用来读或写数据。
Y86的顺序实现
- SEQ处理器:每一个时钟周期上,SEQ执行处理一条完整指令所需的所有步骤。
将处理组织成阶段
- 各个阶段以及各阶段内执行操作:
- 取指:从存储器读取指令字节,地址为程序计数器PC的值
- 译码:从寄存器读入最多两个操作数,得到valA或valB
- 执行:算术/逻辑单元要么执行指令指明的操作,计算存储器引用的有效地址,要么增加或减少栈指针。得到的值为valE。
- 访存:将数据写入存储器,或从存储器中读出数据,读出的值为valM。
- 写回:最多可以写两个结果到寄存器文件
- 更新PC:将PC设为下一条指令的地址
- 执行一条指令需要的处理过程:执行指令所表明的操作、计算地址、更新栈指针、确定下一条指令的地址。
- 对于三种控制转移指令的处理:需要注意位信号Cnd。 在更新PC阶段,检查这个标志,如果这个标志为1,将PC设为valC(跳转目标),如果为0,就设为valP(下一条指令的地址)。
SEQ硬件结构
- 在SEQ中,所有硬件单元的处理都在一个时钟周期内完成。
- SEQ线路图的画图惯例:
- 浅灰色方框表示硬件单元
- 控制逻辑块是用灰色圆角矩形表示的
- 线路的名字在白色椭圆中说明
- 宽度为字长的数据连接用中等粗度的线表示
- 宽度为字节或者更窄的数据连接用细线表示
- 单个位的连接用虚线表示
SEQ的时序
- SEQ的实现包括组合逻辑和两种存储器设备:
- 时钟寄存器 程序计数器和条件码寄存器
- 随机访问存储器 寄存器文件、指令存储器和数据存储器
- 每个时钟周期,程序计数器都会装在新的指令地址;只有在执行整数运算指令时,才会装载条件码寄存器;只有在执行rmmovl、pushl或call指令时,才会写数据存储器;寄存器文件的两个写端口允许每个时钟周期更新两个程序寄存器。
- 组织计算原则:处理器从来不需要为了完成一条指令的执行而去读由该指令更新了的状态。
- 用时钟来控制状态元素的更新,值通过组合逻辑传播。
SEQ阶段的实现
-
取指阶段:
- 以PC为第一个字节的地址,一次读6个字节。
icode
:控制逻辑块计算指令ifun
:功能码- 三个一位的信号(根据icode值计算):
instr_valid
:发现不合法的指令;need_regids
:包含寄存器指示符字节吗;need_valC
:包括常数字吗 - 后五个字节是寄存器指示符字节和常数字的组合编码。
-
译码和写回阶段:
- 都需要访问寄存器文件,根据四个端口的情况,判断应该读哪个寄存器产生信号valA、valB。
- 寄存器文件,支持同时进行两个读和两个写,每个端口有一个地址连接(寄存器ID)和一个数据连接(32根线路),既可以作为寄存器文件的输出字,又可以作为他的输入字。
-
执行阶段:
- 包括算数/逻辑单元(ALU),输出为valE信号。ALU通常作为加法器使用
- 包括条件码寄存器
- 每次运行产生:零、符号、溢出、产生信号set_cc
-
访存阶段
- 读或者写程序数据。
- 两个数据块产生存储器地址和存储器输入证据的值,两个产生控制信号表明应该是读还是写。当执行读操作时,数据存储器产生valM。
- 根据icode,imem_error,instr_valid,dmem_error,从指令执行的结果计算状态码Stat。
-
更新PC阶段
- 产生程序计数器的新值,依据指令的类型和是否要选择分支,新的PC可能是valC、valM或者valP。
流水线的通用原理
- 流水线化的重要特性:增加了系统的吞吐量,即单位时间内服务的顾客总数,不过也会轻微的增加执行时间,即服务一个用户需要的时间。
- 处理器设计的几个重要经验:
- 管理复杂性是首要问题,尽量保持硬件设计的简单。
- 不需要直接实现ISA。
- 一开始就保证设计正确是非常重要的。
- 创建一个流水线化的Y86处理器的好开端。但是,将流水线技术引入一个带反馈的系统,当相邻指令同存在相关时会导致出现问题。
- 流水线控制逻辑必须处理以下4种控制情况,这些情况是其他机制(例如数据转发和分支预测)不能能处理的:
- 处理ret:流水线必须暂停直到ret指令到达写回阶段。
- 加载/使用冒险:流水线必须暂停一个周期。
- 预测错误的分支:在分支逻辑发现不应该选择分支之前,分支目标处的几条指令已经进流水线了。必须从流水线中去掉这些指令。
- 异常:当―条指令导致异常,我们想要禁止后面的指令更新程序员可见的状态,并睏异常指令到达写回阶段时,停止执行。
Y86模拟器的安装
- 可以参考这篇帖子:(http://www.cnblogs.com/hrhguanli/p/4594724.html),上面的教程写的非常详细,安装成功后效果如图所示:
遇到的问题及解决过程
-
输入
make asuml.yo
指令出现错误:
-
Makefile没有问题,主要原因是第一次已经make过一遍了,第二次如果没有修改过直接编译就会出现错误,可以先
make clean
一下,再make
就没有问题了:
家庭作业
- 家庭作业4.45题C语言代码
- 编写了一个main函数,对mybubble函数进行了测试,测试结果如下:
本周代码托管
代码托管地址:click here
心得体会
这周主要学习了Y86指令体系结构和硬件控制语言HCL,其实Y86只是作者定义的一个指令集体系结构,目的就是为了让我们更加清晰的去了解ISA,对我们来说,去设计指令集几乎不大可能,但是我们能从中了解CPU处理指令的流程以及它的工作原理,学习它的思想,这对我们今后的学习会有一些启发。很多时候,这种启发是很重要并且难得的,或许我们就是缺少一些这样的启发,学习的进度才会停滞不前吧。
学习进度条
代码行数(新增/累积) | 博客量(新增/累积) | 学习时间(新增/累积) | 重要成长 | |
---|---|---|---|---|
目标 | 5000行 | 30篇 | 400小时 | |
第一周 | 0/0 | 1/2 | 25/45 | 学习了几个Linux核心命令 |
第二周 | 55/55 | 2/4 | 27/72 | 学会了vim,gcc以及gdb的基本操作 |
第三周 | 148/203 | 1/5 | 23/95 | 对信息的表示和处理有更深入的理解 |
第五周 | 72/275 | 1/6 | 25/120 | 对汇编语言有了更深的理解 |
第六周 | 56/331 | 2/8 | 30/150 | 安装了Y86模拟器 |