20145218 《信息安全系统设计基础》第5周学习总结
20145218 《信息安全系统设计基础》第5周学习总结
教材学习内容总结
4.1Y86指令集体系结构
- ISA:指令集体系结构,一个处理器支持的指令和指令的字节级编码程序员可见的状态
程序员可见的状态
Y86程序中的每条指令都会读取或修改处理器状态的某些部分,称为程序员可见状态。其中包括:
- 8个程序寄存器:%eax,%ecx,%edx,%ebx,%esi,%edi,%esp和%ebp。
- 条件码:ZF(零)、SF(符号)、OF(有符号溢出)
- 程序计数器(PC):存放当前正在执行的指令的地址
- 存储器:很大的字节数组,保存着程序和数据。Y86系统用虚拟地址来引用存储器的位置,硬件和操作系统软件联合起来将虚拟地址翻译成实际或者物理地址。
- 状态码(stat):表明程序执行的总体状态。(异常处理)
Y86指令
- movl:irmovl、rrmovl、mrmovl、rmmovl,分别显式地指明源和目的地的格式。第一个字母表明源的类型,i(立即数)、r(寄存器)或m(存储器 ),第二个字母代表目的,可以是r或者m。
注意:
1.两个存储器传送指令中的存储器引用方式是简单地基址和偏移量形式,即:
Imm(Eb) M[Imm+R[Eb]](基址+偏移量)寻址
2.不允许从一个存储器地址直接传送到另一个存储器地址,也不允许将立即数传送到存储器。
- OPl(整数操作指令):addl、subl、andl和xorl。只对寄存器数据进行操作,同时还设置条件码。
- jXX(跳转指令):jmp、jle、jl、je、jne、jge、jg,根据分支指令的类型和条件码的设置来选择分支。
- cmovXX(条件传送指令):cmovle、cmovl、cmove、cmovne、cmovge和comvg,与寄存器-寄存器传送指令rrmovl一样,但只有当条件码满足所需要的约束时才会更新目的寄存器的值。
- call和ret:call指令将返回地址入栈,然后跳转到目的地址。ret指令从这样的过程调用中返回。
- pushl和popl:入栈和出栈。
- halt:停止指令的执行。
指令编码
- 指令的字节级编码规则:高4位为代码部分,低四位为功能部分,功能值只有在一组相关指令共用一个代码时才有用。
- 8个程序寄存器当中,每个都有相应的0~7的寄存器标识符。程序寄存器存在CPU中的一个寄存器文件中,这个文件就是一个小的、以寄存器ID作为地址的随机访问存储器。
数字 寄存器名字
0 %eax
1 %ecx
2 %edx
3 %ebx
4 %esp
5 %ebp
6 %esi
7 %edi
- 附加寄存器指示符字节:指定一个或者两个寄存器。
- 附加4字节的常数字:作为irmovl的立即数数据,rmmovl和mrmovl的地址指示符的偏移量,以及分支指令和调用指令的目的地址。
注意:分支指令和调用指令的目的地址是一个绝对地址。所有整数采用小端法编码。
Y86异常
- 状态码:描述程序执行的总体状态。
值 名字 含义
1 AOK 正常操作
2 HLT 处理器执行halt指令(指令停止)
3 ADR 遇到非法地址
4 INS 遇到非法指令
- Y86中,任何AOK以外的代码都会使处理器停止执行指令,而没有异常处理程序。
4.2逻辑设计和硬件控制语言HCL
实现一个数字系统需要的三个组成部分:计算对位进行操作的函数的组合逻辑、存储位的存储器元素,以及控制存储器元素更新的时钟信号。
计算对位进行操作的函数的组合逻辑
- 逻辑门是数字电路的基本计算元素,输出等于输入位值的某个布尔函数。
And:out=a&&b
Or:out=a||b
Not:out=!a
异或:out=(!a)b+a(!b)
- 组合电路:很多逻辑门组合成一个网,构建的计算块
注意:
1.两个以上的逻辑门的输出不能连接在一起,否则可能使线上信号矛盾,导致一个不合法的电压或电路故障。
2.这个网必须是无环的,否则会导致网络计算有歧义。
3.多路复用器:(s&&a)||(!s&&b)(控制信号为输入位S,S为1时输出a,s为0时输出b)
- 字级的组合电路:HCL中,所有字级的信号都声明为int,不指定字的大小。
- 多路复用函数是用情况表达式来描述的。
[
select1 : expr_1
select2 : expr_2
......
selectk : expr_k
]
- 算数/逻辑单元(ALU):三个输入分别为标号为A和B的两个数据输入,和一个控制输入。(注意减法的操作数顺序)
- 集合关系:判断集合关系的通用格式是
iexpr in {iexpr1,iexpr2,....iexprk}
(其中被测试和待匹配的值均为整数表达式。)
存储器和时钟
- 为了产生时序电路,必须引入按位存储信息的设备,存储设备由同一个时钟信号控制。
- 随机访问存储器:存储多个字,用地址来选择应该读写哪个字。
- 时钟寄存器:存储单个位或字,时钟信号控制寄存器加载输入值。
- 寄存器首先保持稳定(输出等于当前状态),时钟上升沿来到时,加载输入信号。Y86处理器用时钟寄存器保存程序计数器(PC),条件代码(CC)和程序状态(Stat)。
- 寄存器文件有两个读端口(A和B),一个写端口(W),允许同时进行多端口读写操作。
4.3 Y86顺序实现
将处理组织成阶段
- 取指:从存储器读取指令字节,地址为程序计数器(PC)的值。指令指示符字节两个四位部分,称为icode(指令代码)和ifun(指令功能)。vaIP(下一条指令的地址)=PC+已取出指令的长度。
- 译码:从寄存器文件读入最多两个操作数,得到valA和/或valB。
- 执行:算数逻辑单元(ALU)根据ifun的值执行指令指明的操作,计算存储器引用的有效地址,或者增加或减少栈指针。得到的值称为valE。也可根据条件码执行跳转。
- 访存:将数据写入存储器,或者从存储器读出数据。读出的值为valM。
- 写回:最多可以写两个结果到寄存器文件。
- 更新PC:将PC设置成下一条指令的地址。
SEQ硬件实现
- 取指:将程序计数器寄存器作为地址,指令存储器读取指令的字节。PC增加器计算valP,即增加了的程序计数器。
- 译码:寄存器文件有两个读端口A和B,从这两个端口同时读寄存器的值valA和valB。
- 执行:根据指令类型将算数/逻辑单元(ALU)用于不同的目的。条件码寄存器有三个条件码位,ALU负责计算条件码的新值,当执行跳转指令时会根据条件码和跳转类型来计算分支信号Cnd。
- 访存:数据存储器读出或写入一个存储器字。指令和数据存储器访问的是相同的存储器位置,但用于不同的目的。
- 写回:寄存器文件有两个写端口,E用来写ALU计算出来的值,M用来写从数据存储器中读出来的值。
SEQ的时序
- Y86指令集的计算原则:处理器从来不需要为了完成一条指令的执行而去读由该指令更新了的状态。
SEQ阶段的实现
- 取指阶段:包括指令存储器硬件单元。
- 译码和写回阶段:寄存器文件,支持同时进行两个读和两个写,每个端口有一个地址连接(寄存器ID)和一个数据连接(32根线路),既可以作为寄存器文件的输出字,又可以作为他的输入字。
- 执行阶段:算数逻辑单元(ALU),输出为valE信号。
- 访存阶段:读或者写程序数据,两个控制块产生存储器地址和存储器输入数据的值。另外两个块产生控制信号表明应该执行读还是写操作。当执行读操作时,数据存储器产生valM。
- 更新PC阶段:产生程序计数器的新值,依据指令的类型和是否要选择分支,新的PC可能是valC、valM或者valP。
Y86模拟器安装教程
参考博客:http://www.cnblogs.com/hrhguanli/p/4594724.html
-
安装bison和flex词法分析工具,在终端中输入
sudo apt-get install bison flex
-
下载sim解压。地址
http://csapp.cs.cmu.edu/public/students.html
(注意:使用校网很可能打不开,最好使用其他网络)找到
Chapter 4: Processor Architecture
,点击Source distribution (README)
如下图所示,下载后在虚拟机中解压。
-
图形界面须要安装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
现在模拟器就可以用了,例如pipe文件夹下在终端中打开,输入 ./psim -t -g ../y86-code/asum.yo
-
进入y86-code文件夹,可以找到asuml.yo
- 若我们想多练习的话,可以在文件夹y86-code中新建文档输入P251页代码,命名文P251lianxi.ys,在文件中右键选择在终端中打开,首先
make clean
一下,然后这时只剩.ys文件了,然后可以make P251lianxi.yo
,然后可以cat P251lianxi.yo
查看,如下图所示,make all
可以汇编运行所有代码
课本练习题
注意:做练习题1、2时,参照P232图4-2和P234图4-4两张表就可以轻松做出
练习题4.1
确定下面的Y86指令序列的字节编码。.pos 0x100表明这段代码的起始地址应该是0x100
irmovl $15,%ebx
rrmovl %ebx,%ecx
loop:
rmmovl %ecx,-3(%ebx)
addl %ebx,%ecx
jmp loop
答:
irmovl $15,%ebx ##30f30f000000
rrmovl %ebx,%ecx ##2031
loop:
rmmovl %ecx,-3(%ebx) ##4013fdffffff
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
【此题应该是在熟练掌握各项指令(尤其是特殊指令)的编码基础上进行尝试分解编码序列。例如:在以“a0”开头的编码处,就应该意识到这是一个之后2字节的pushl指令;然后下一个以“80”开头的即call指令(只有五字节),这样就可以得出剩余的00一定是halt。】
C.
0x300:505407000000 ##mrmovl 0x7(%esp),%ebp
0x306:10 ##nop
0x307:f0 ##非法
0x308:b01f ##popl %ecx
练习题4.5
修改P238图4-6中的Y86代码,实现函数AbsSum,使其能计算一个数组的绝对值的和。在内循环中使用条件传送指令。
源代码:
int Sum(int *Start,int Count)
{
int sum = 0;
while(Count)
{
sum+=*Start;
Start++;
Count--;
}
return sum;
}
对于内循环的Y86代码,如要计算绝对值之和,只需要在相对于“sum+=*Start”的部分做下改动,加上条件分支(负数取反,正数不变)。如果要用条件传送,则适合cmovg或者cmovge
loop:
mrmovl (%ecx),%esi
irmovl $0,%edi
subl %esi,%edi
cmovg %edi,%esi ##以上代码处理了x<0的情况,下面即和原代码相同
addl %esi,%eax
irmovl $4,%ebx
addl %ebx,%ecx
irmovl $-1,%ebx
addl %ebx,%edx
jne loop
练习题4.8
写出信号xor的HCL表达式,xor就是异或,输入为a和b。信号xor和上面定义的eq有什么关系?
- bool xor = (a && !b) || (!a && b)
- 与bool eq = (!a && !b) || (a && b)的区别为:二者互补
练习题4.10
写一个电路的HCL代码,对于输入字A,B,C,选择中间值。
int Med3 = [
A<=B && A>=C :A;
A<=C && A>=B :A;
B<=A && B>=C :B;
B<=C && B>=A :B;
1:C;
];
练习题4.17
写出SEQ中实现need_valC的HCL代码
bool need_valC = icode in {IIROMVL,IRMMOVL,IMRMOVL,IJXX,ICALL};
感悟
我从这周的阅读开始发现:书中有部分内容确实是比较晦涩的,并不是语言本身表述性问题,而是中英翻译之间所存在的必然性障碍;中英文信息量差异以及表达习惯的不同使得译文可能与中文仍存在一些差异。有时候我们读到的东西不管第一遍读的有多认真,总是什么也记不住,所以,反复阅读的效果格外显著。由不懂到懂,相当欢乐。
本周代码托管截图
代码托管链接:https://git.oschina.net/senlinmilelu/ISdesign20145218
学习进度条
代码行数(新增/累积) | 博客量(新增/累积) | 学习时间(新增/累积) | 重要成长 | |
---|---|---|---|---|
目标 | 5000行 | 30篇 | 400小时 | |
第一周 | 200/200 | 2/2 | 20/20 | |
第二周 | 300/500 | 3/4 | 18/38 | |
第三周 | 500/1000 | 4/7 | 22/60 | |
第四周 | 300/1300 | 4/9 | 30/90 | |
第五周 | 500/1000 | 5/7 | 22/60 | |
第六周 | 300/1300 | 6/9 | 30/90 |