每条指令都会读取或修改处理器状态的某些部分,称为程序员可见状态。
1、8个程序寄存器:%eax,%ecx,%edx,%ebx,%esi,%edi,%esp和%ebp。
2、条件码:ZF(零)、SF(符号)、OF(有符号溢出)
3、程序计数器(PC):存放当前正在执行的指令的地址
4、存储器:很大的字节数组,保存着程序和数据。Y86系统用虚拟地址来引用存储器的位置,硬件和操作系统软件联合起来将虚拟地址翻译成实际或物理地址。
5、状态码(stat):表明程序执行的总体状态。(异常处理)
IA32 movl指令:irmovl,rrmovl,mrmovl,rmmovl
(1)源操作数:i-立即数;r-寄存器;m-存储器
(2)目的操作数:r-寄存器;m-存储器
(3)指令附加的寄存器指示符字节依次是数据源(如果是立即数,把这一位设置成0xf)、目的寄存器/基址寄存器。 (4)有些指令需要附加四字节的常数字,采用小端法(倒序)编码
addl加
subl减
andl与
xorl异或
三个条件码:
ZF-零
SF-符号
OF-溢出
jmp 直接跳转
jle(SF^OF)|ZF 有符号数≤
jl SF^OF 有符号<
je ZF 相等/零
jne ~ZF 不相等/非零
jge ~(SF^OF) 有符号≥
jg ~(SF^OF)&~ZF 有符号>
根据分支指令的类型和条件码的设置来选择分支。
cmovle
cmovl
cmove
cmovne
cmovne
cmovg
与寄存器-寄存器传送指令rrmovl一样,但只有当条件码满足所需要的约束时才会更新目的寄存器的值。
call:返回地址入栈,然后跳到目的地址;
ret指令从这样的过程调用中返回。
入栈和出栈
停止指令的执行
1、指令的字节级编码。每条指令需要1-6个字节不等。每条指令的第一个字节表明指令的类型。
该字节分为两个部分,每部分4位:高4位是代码部分,低4位是功能部分。功能值只有在一组相关指令共用一个代码时才有用。
2、整数操作:代码部分均为6,功能部分区分addl,subl,andl,xorl
分支指令:代码部分均为7
传送指令:代码部分均为2
3、8个程序寄存器当中,每个都有相应的0~7的寄存器标识符。
4、程序寄存器存在CPU中的一个寄存器文件中,这个文件就是一个小的、以寄存器ID作为地址的随机访问存储器。
5、有的指令只有一个字节,而有的需要操作数的指令编码更长一点,就可能有附加的寄存器指示符字节,指定一个或两个寄存器,这些寄存器字段为rA,rB
6、附加4字节的常数字:这个字作为irmovl的立即数数据,rmmovl和mrmovl的地址指示符的偏移量,以及分支指令和调用指令的目的地址。
AOK 正常操作
HLT 处理器执行一条halt指令(指令停止)
ADR 遇到非法地址
INS 遇到非法指令
Y86——处理器停止运行指令。
1.需要多条指令来执行一条IA32指令所完成的功能
2.以“.”开头的词是编辑器命令
3.命令 .pos0告诉编辑器应该从地址0处开始产生代码,这个地址是所有Y86程序的起点
4.声明标号Steak,并用一个.pos命令指明地址0x100
电子电路中,用1.0V左右的高电压表示逻辑1,用0.0V左右的低电压表示逻辑0。
AND Y=a&&b
OR Y=a||b
NOT Y=!a
很多逻辑门组合成一个网,构建计算块。构建这些网有两条限制。
1、两个或多个逻辑门的输出不能连在一起,否则可能会使线上的信号矛盾,导致一个不合法的电压或电路故障
2、这个网必须是无环的
所有字级的信号都声明为int,并不指定字的大小
多路复用函数是用情况表达式来描述的,格式如下:
[ select_1 : expr_1 select_2 : expr_2 …… select_k : expr_k ]
从逻辑上讲,这些选择表达式是顺序求值的。
不同选择表达式之间允许不互斥
通用格式:
iexpr in {iexpr1,iexpr2,...,iexprk}
其中被测值iexpr和待匹配的值iexpr1-iexprk均为整数表达式。
组合电路简单的响应输入信号,产生等于输入的某个函数的输出,并存在状态在这个状态上进行计时,如此产生了时序电路。
随机访问存储器:存储多个字,用地址来选择应该读写哪个字。
时钟寄存器:存储单个位或字,时钟信号控制寄存器加载输入值。
硬件寄存器工作时,每当每个时钟到达上升沿时,值才会从寄存器的输入传送到输出。 寄存器文件读数据是一个地址为输入,数据为输出的组合逻辑块,写入字是由时钟信号控制的。
1、取指:从存储器读取指令字节,地址为程序计数器(PC)的值。指令指示符字节两个四位部分,称为icode(指令代码)和ifun(指令功能)。vaIP(下一条指令的地址)=PC+已取出指令的长度。
2、译码:从寄存器文件读入最多两个操作数,得到valA和/或valB。
3、执行:算数逻辑单元(ALU)根据ifun的值执行指令指明的操作,计算存储器引用的有效地址,或者增加或减少栈指针。得到的值称为valE。也可根据条件码执行跳转。
4、访存:将数据写入存储器,或者从存储器读出数据。读出的值为valM。
5、写回:最多可以写两个结果到寄存器文件。
6、更新PC:将PC设置成下一条指令的地址。
1、取指:将程序计数器寄存器作为地址,指令存储器读取指令的字节。PC增加器计算valP,即增加了的程序计数器。
2、译码:寄存器文件有两个读端口A和B,从这两个端口同时读寄存器的值valA和valB。
3、执行:根据指令类型将算数/逻辑单元(ALU)用于不同的目的。条件码寄存器有三个条件码位,ALU负责计算条件码的新值,当执行跳转指令时会根据条件码和跳转类型来计算分支信号Cnd。
4、访存:数据存储器读出或写入一个存储器字。指令和数据存储器访问的是相同的存储器位置,但用于不同的目的。
5、写回:寄存器文件有两个写端口,E用来写ALU计算出来的值,M用来写从数据存储器中读出来的值。
四个硬件单元:
1、程序计数器
2、条件码寄存器
3、数据存储器
4.寄存器文件
它们通过一个时钟信号来控制。
Y86指令集的计算原则: 处理器从来不需要为了完成一条指令的执行而去读由该指令更新了的状态
1、取指阶段,包括指令储存器硬件单元
2、译码和回写阶段
3、执行阶段,包括算数/逻辑单元
4、访存阶段,读或写程序数据
5、更新PC阶段
6、SEQ小结
(1)构建YIS环境:
cd ~/Code/shiyanlou_cs413 wget http://labfile.oss.aliyuncs.com/courses/413/sim.tar tar -xvf sim.tar cd sim sudo apt-get install tk sudo ln -s /usr/lib/x86_64-linux-gnu/libtk8.6.so /usr/lib/libtk.so sudo ln -s /usr/lib/x86_64-linux-gnu/libtk8.6.so /usr/lib/libtk.so make
(2)测试教材P239代码asuml.ys,得到代码:
| /* $begin code-yso */ | /* $begin code-ysa */ | # Execution begins at address 0 | # This version uses a leave instruction 0x000: | .pos 0 0x000: 30f400040000 | init: irmovl Stack, %esp # Set up Stack pointer 0x006: 30f500040000 | irmovl Stack, %ebp # Set up base pointer 0x00c: 7024000000 | jmp Main # Execute main program | | # Array of 4 elements 0x014: | .align 4 0x014: 0d000000 | array: .long 0xd 0x018: c0000000 | .long 0xc0 0x01c: 000b0000 | .long 0xb00 0x020: 00a00000 | .long 0xa000 | 0x024: 30f004000000 | Main: irmovl $4,%eax 0x02a: a00f | pushl %eax # Push 4 0x02c: 30f214000000 | irmovl array,%edx 0x032: a02f | pushl %edx # Push array 0x034: 803a000000 | call rSum # Sum(array, 4) 0x039: 00 | halt | | # int Sum(int *Start, int Count) 0x03a: a05f | rSum: pushl %ebp 0x03c: 2045 | rrmovl %esp,%ebp 0x03e: 30f014000000 | irmovl $20,%eax 0x044: 6104 | subl %eax,%esp 0x046: a03f | pushl %ebx 0x048: 503508000000 | mrmovl 8(%ebp),%ebx 0x04e: 50050c000000 | mrmovl 12(%ebp),%eax 0x054: 6200 | andl %eax,%eax 0x056: 718b000000 | jle L38 0x05b: 30f2f8ffffff | irmovl $-8,%edx 0x061: 6024 | addl %edx,%esp 0x063: 30f2ffffffff | irmovl $-1,%edx 0x069: 6020 | addl %edx,%eax 0x06b: a00f | pushl %eax 0x06d: 30f204000000 | irmovl $4,%edx 0x073: 2030 | rrmovl %ebx,%eax 0x075: 6020 | addl %edx,%eax 0x077: a00f | pushl %eax 0x079: 803a000000 | call rSum 0x07e: 502300000000 | mrmovl (%ebx),%edx 0x084: 6020 | addl %edx,%eax 0x086: 708d000000 | jmp L39 0x08b: 6300 | L38: xorl %eax,%eax 0x08d: 5035e8ffffff | L39: mrmovl -24(%ebp),%ebx 0x093: d0 | leave 0x094: 90 | ret | 0x400: | .pos 0x400 0x400: | Stack: # The stack goes here | /* $end code-ysa */ | /* $end code-yso */
1、先是没有找到Y86模拟器安装入口
应该将sim得压缩包解压,最后成功连接Y86
1、教材《深入理解计算机系统》
2、实验楼实验指导书《深入理解计算机系统》:https://www.shiyanlou.com/courses/413 实验五
3、Y86 Tools:http://csapp.cs.cmu.edu/2e/students.html