20145221 《信息安全系统设计基础》第6周学习总结
处理器体系结构
Y86指令集体系结构
- 内容:定义一个指令集体系结构,包括定义各种状态元素、指令集和它们的编码、一组编程规范和异常事件处理
程序员可见状态:
- Y86程序中的每条指令都会读取或修改处理器状态的某些部分。
- Y86具体包括:8个程序寄存器、3个条件码ZFSFOF、程序计数器(PC)。
- Y86用虚拟地址引用存储器位置。 程序状态的最后一个部分是状态码Stat,它表明程序执行的总体状态。
Y86指令
Y86指令
- 指令介绍:
- halt:这个指令将会终止指令的执行
- nop:这是一个占位指令,他不做任何事,后续为了实现流水线,它有一定的作用
- xxmovl:这是一系列的数据传送指令,其中r代表寄存器,m代表存储器,i代表立即数.比如rrmov指令,则代表将一个寄存器的值,赋给另外一个寄存器
- 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的相对地址.
- 相关编码详情见课本P233-P234
Y86异常
- 对Y86来说,程序员可见的状态中就有stat状态码,它标志了程序执行的状态.Y86需要有能力根据stat去做一些处理.捕获为了简单起见,这里除了正常执行之外,都将停止指令的执行.真实当中,会有专门的异常处理程序.
- Y86有四种不同的状态码:AOK(正常),HTL(执行halt指令),ADR(非法地址)和INS(非法指令).
Y86程序
- Y86指令和IA32代码的主要区别在于,它可能需要多条指令来执行一条IA32指令能完成的所有功能。
- Y86没有伸缩寻址模式。
- 以“.”开头的词是汇编器命令,命令.pos0告诉汇编器应该从地址0处开始产生代码。
- 创建Y86代码的唯一工具是汇编器。
- YIS:指令集模拟器
- Y86和X86的区别在于,有的时候Y86需要两条指令来达到X86一条指令就可以达成的目的.
- 比如对于X86指令中的addl $4,%ecx这样的指令,由于Y86当中的addl指令不包含立即数,所以Y86需要先将立即数存如寄存器,即使用irmovl指令,然后再使用addl来处理加法运算.
- 总的来说,Y86就是X86的一个缩减版,他的目的就是以简单的结构来实现一个处理器,帮助我们了解处理器的设计和实现.
一些Y86指令的详情
- 大多数Y86指令是以一种直接的方式修改程序状态的。
- 执行pushl和popl指令时,处理器的行为是不确定的,因为要入栈的寄存器会被同一条指令修改。通常有两种约定:
- 压入/弹出%esp的原始值
- 压入/弹出%esp-/+4后的值
逻辑设计和硬件控制语言HCL
逻辑门
- 逻辑门是数字电路的基本计算元素,它们的输出,等于它们输入位值的某个布尔函数。
- 逻辑门总是活动的,一旦一个门的输入变化,在短时间内,输出就会跟着变化。。
组合电路和HCL布尔表达式
- 组合电路:将很多的逻辑门组合成一个网,能构建计算块。
- 多路复用:根据输入控制信号的值,从一组不同的数据信号中选出一个。
- 构建这些网有2条限制:
- (1)两个或多个逻辑门的输出不能连接在一起
- (2)这个网必须是无环的。
- HCL表达式和C语言中逻辑表达式的区别:
- (1)组合逻辑电路的输出会持续地响应输入的变化;C表达式只有在程序执行过程中被遇到时才会求值。
- (2)C的逻辑表达式允许参数是任意整数,0表示FLASE,其他任何值都表示TRUE;逻辑门只对位值0和1进行操作。
- (3)C的逻辑表达式可能只被部分求值;组合逻辑没有部分求值的规则,逻辑门只是简单地响应输入的变化。
字级的组合电路和HCL整数表达式
- 执行字级计算的组合电力根据输入字的各个为,用逻辑门来计算输出字的各个位。
- 用中等粗度的线来表示携带字的每个位的线路,用虚线来表示布尔信号结果。
- 在HCL中,多路复用函数用情况表达式来描述。
- 算术/逻辑单元是一种很重要的组合电路。
集合关系
- 判断集合关系的通用格式是:
iexpr in {iexpr1,iexpr2,……,iexprk}
存储器和时钟
- 存储设备都是由同一个时钟控制,两类存储器设备包括:
- 时钟寄存器(寄存器):储存单个位或字,用时钟信号控制寄存器加载输入值。
- 随机访问储存器(储存器):储存多个字,用地址选择该读/写哪个字。
- 硬件和机器级编程中的寄存器有细微差别,分为称为“硬件寄存器”和“程序寄存器”。
- 在硬件中,寄存器直接将它的输入和输出线连接到电路的其他部分;
- 在机器级编程中,寄存器代表的是CPU中为数不多的可寻址的字,这里的地址是寄存器ID。 Y86处理器会用时钟寄存器保存程序计数器(PC)、条件代码(CC)、程序状态(Stat)。
- Y86处理器会用时钟寄存器保存程序计数器PC,条件代码CC和程序状态Stat。
- 处理器有一个随机访问存储器来存储程序数据。
- 处理器还包括另外一个只读存储器,用来读指令。
- 在大多数实际系统中,这两个存储器被合并为一个具有双端口的存储器:一个用来读指令,一个用来读或写数据。
Y86的顺序实现
- SEQ处理器:每一个时钟周期上,SEQ执行处理一条完整指令所需的所有步骤。
将处理组织成阶段
- 取址:valP:PC的值加上已取出指令的长度。
- 译码:读入指令rA和rB字段指明的寄存器。
- 执行:ALU执行指令指明的操作,计算存储器引用的有效地址,要么增加或者减少栈指针,得到的值为valE;
- 跳转指令来说,这个阶段会检验条件码和分支条件。
- 访存:可以将数据写入存储器,或者从存储器读出数据。置为valM。
- 写回:最多可以写两个结果到寄存器文件。
- 更新:将PC设置成下一条指令的地址。
SEQ硬件结构
- 实现所有Y86指令所需要的计算可以组织成6个阶段:取值、译码、执行、访存、写回和更新PC。 在SEQ中,所有硬件单元的处理都在一个时钟周期内完成。
- SEQ线路图的画图惯例:
- 浅灰色方框表示硬件单元
- 控制逻辑块是用灰色圆角矩形表示的
- 线路的名字在白色椭圆中说明
- 宽度为字长的数据连接用中等粗度的线表示
- 宽度为字节或者更窄的数据连接用细线表示
- 单个位的连接用虚线表示
SEQ的时序
- SEQ的实现包括组合逻辑和两种存储器设备:时钟寄存器(程序计数器和条件码寄存器),随机访问存储器(寄存器文件、指令存储器和数据存储器)。
- 每个时钟周期,程序计数器都会装在新的指令地址;只有在执行整数运算指令时,才会装载条件码寄存器;只有在执行rmmovl、pushl或call指令时,才会写数据存储器;寄存器文件的两个写端口允许每个时钟周期更新两个程序寄存器。
SEQ阶段的实现
- 在控制逻辑中必须被显式引用的常数:
1.取指阶段
- 以PC为第一个字节的地址,一次读6个字节。
- icode:控制逻辑块计算指令
- ifun:功能码
- 三个一位的信号(根据icode值计算):
- instr_valid:发现不合法的指令;
- need_regids:包含寄存器指示符字节码;
- need_valC:包括常数字码
- 后五个字节是寄存器指示符字节和常数字的组合编码。
2.译码和写回阶段
- 都需要访问寄存器文件,根据四个端口的情况,判断应该读哪个寄存器产生信号valA、valB。
- 寄存器文件,支持同时进行两个读和两个写,每个端口有一个地址连接(寄存器ID)和一个数据连接(32根线路),既可以作为寄存器文件的输出字,又可以作为他的输入字。
3.执行阶段
- 包括算数/逻辑单元(ALU),输出为valE信号。ALU通常作为加法器使用
- 包括条件码寄存器
- 每次运行产生:零、符号、溢出、产生信号set_cc
4.访存阶段
- 读或者写程序数据。
- 两个数据块产生存储器地址和存储器输入证据的值,两个产生控制信号表明应该是读还是写。当执行读操作时,数据存储器产生valM。
- 根据icode,imem_error,instr_valid,dmem_error,从指令执行的结果计算状态码Stat。
5.更新PC阶段
- 产生程序计数器的新值,依据指令的类型和是否要选择分支,新的PC可能是valC、valM或者valP。
教材学习中的问题和解决过程
安装Y86模拟器遇到的问题
-
可以参考20145218张晓涵的博客,里面写的非常详细,结果如下:
-
拿
asum.yo
为例,用Y86打开如下图,看起来是很直观的 -
但是之前在安装
sudo apt-get install bison flex
时出现了问题如下图所示: -
解决办法1:
#:ps -aux (列出进程,形式如)
root 5765 0.0 1.0 18204 15504 ? SN 04:02 0:00 apt-get -qq -d
找到最后一列以apt-get 开头的进程
#:sudo kill -9 该进程的PID
- 解决办法2:
#:sudo rm /var/cache/apt/archives/lock
#:sudo rm /var/lib/dpkg/lock
YIS测试
asuml.ys
汇编后得到asuml.yo
本周代码托管
-
代码截图
其他(感悟、思考等,可选)
- 首先,我觉得本周的学习任务是对上学期汇编的一个巩固,在原有我们所学的8086汇编知识的基础上得到了拓宽,这次我们所学的汇编主要是在32位机器上的。在寄存器个数没有变化的前提下,所能支持的位数翻了一倍,引入了
%eax, %ebx, %ebp...
等寄存器,操作指令也由原来的向左赋值变为向右赋值。虽然变化挺多,但本质是不变的一条机器指令只执行一个非常基本的操作以及汇编语言是近似机器语言,其造作指令与机器码一一对应(这在我们反汇编的实践中体现的很好)。 - 其次,在课后的练习以及家庭作业中,首次接触到了逆向工程的概念,即通过阅读汇编代码,得出原有C语言文件里的相关知识的工作。我也用该方法成功解决了几道题目,让我再次感受到了汇编语言的巨大魅力,虽然汇编语言可移植性不强,但专门用来对付某台机器上的C语言可是绰绰有余,可以帮我们挖掘到更多的信息。
学习进度条
代码行数(新增/累积) | 博客量(新增/累积) | 学习时间(新增/累积) | 重要成长 | |
---|---|---|---|---|
目标 | 5000行 | 30篇 | 400小时 | |
第一周 | 200/200 | 2/2 | 20/20 | 学习了Linux常用命令 |
第二周 | 79/279 | 1/3 | 30/50 | 了解vim,gcc,gdb基本操作 |
第三周 | 182/461 | 1/4 | 25/75 | 更深层次了解信息处理 |
第四周 | 36/497 | 2/6 | 3/78 | 第二章知识简单的运用 |
第五周 | 194/691 | 1/7 | 28/106 | 汇编知识与了解逆向 |
第六周 | 520/1211 | 1/8 | 27/133 | Y86处理器,了解ISA抽象 |