CSAPP——Y86-64顺序实现(4.3)

介绍:

Y86为CSAPP书中为方便学习而简化的X86。Y86顺序结构的是无流水线的结构(SEQ):在一个足够长的时钟周期上,该结构会完成一条完整的汇编指令。每个汇编指令有6个执行阶段。

 

一、六个基本阶段

取指——译码——执行——访存——写回——更新PC

 

二、各阶段主要功能

1、取指:计算当前指令的长度,获取需要用到的寄存器和立即数

2、译码:从寄存器中读取数据

3、执行:算数逻辑单元(ALU)执行三类计算:算数逻辑运算、计算内存引用有效地址、针对push和pop等计算栈指针的增减

4、访存:从内存读取数据 or 将数据写入内存

5、写回:将数据写入寄存器

6、更新pc:设置下一条指令的地址

 

三、各阶段详解 

1、取值阶段

  输入:机器码        输出:icode、ifun、rA、rB、valC

  首先从PC寄存器指向的位置取10字节(Y86中最长的指令的长度)作为当前指令,以保证在任何情况下指令都是完整的,再根据接下来的步骤确定指令的真正长度。10个字节中的第1个字节为操作码,包含icode和ifun。

CSAPP——Y86-64顺序实现(4.3)

图1:icode和ifun对应的指令

 

 

  其中,icode占第1个字节中的高4位,称为指令代码,表示该条指令的分类。ifun占低4位,称为指令功能,表示指令的具体功能。硬件根据icode可以判断指令是否合法。此外,还可以根据icode判断当前指令是否需要寄存器,需要几个寄存器,是否需要立即数,以确定当前指令的真正长度,分四种情况:

(1)寄存器+立即数:说明该指令长度就是10Bytes。其中第2个字节为寄存器标识符rA和rB(rA占高4位,rB占低4位)若需要两个寄存器,则rA和rB都按对应规则进行标识,若只需要一个,不需要的寄存器对应的标识符变为0xF,另一个正常标识。第3到10个字节为立即数(valC)。10个字节全部保留。

(2)仅立即数:该指令长度为9Bytes。第2到9个字节为立即数valC,第10个字节给下一条指令用。

(3)仅寄存器:指令长度为2Bytes。第2个字节为rA和rB,根据需要1个 or 2个寄存器,同(1)理处理rA和rB,第3到10字节给下一条指令。

(4)什么也不需要:该指令长度1Bytes。第2到10字节给下一条指令。

CSAPP——Y86-64顺序实现(4.3)

 

图2:寄存器标识符rA和rB与寄存器的对应规则,图中number均占4个bit

 

CSAPP——Y86-64顺序实现(4.3)

 

 

图3:Y86的一些汇编指令,包含了前文所述的4种情况

 

2、译码

  输入:icode、rA、rB         中间变量:srcA、srcB         输出:valA、valB

  硬件电路通过rA、rB和icode的值,找到最后要用到的寄存器srcA和srcB。rA和rB为寄存器标识符,与寄存器有对应规则,可以产生出srcA和srcB。之所以需要用到icode,是因为有些指令除了rA or rB外,还需要知道栈顶指针rsp的值,例如:pushq rA  该指令将rA对应的寄存器中的值压入栈中,因此需要rsp找到栈顶位置,rA对应的寄存器和rsp寄存器作为srcA和srcB。除了push外,还有pop、call、ret需要rsp。根据srcA和srcB,找到对应寄存器,并得到其中所存的数据,为valA和valB。

 

3、执行:

  输入:icode、ifun、valA、valB、valC        中间变量:ALUA、ALUB、ALUfun、CC       输出:Cnd、valE

 

CSAPP——Y86-64顺序实现(4.3)

 

图4:执行阶段

 

   算数逻辑单元(ALU)主要执行三类计算:算数运算和逻辑运算、计算内存引用有效地址、计算栈指针的增减。对于ALU,数据输出包括:(1)valE:计算结果。(2)Cnd:跳转指令标识,对于跳转指令,若Cnd==1则跳转,Cnd==0则不跳转。对于Cnd,需要由icode决定是否需要设置CC,因为只有跳转指令需要判断是否跳转,当前指令是否为跳转指令由icode判断;还需要ifun来决定最后是否跳转,因为ifun中指明了跳转条件(见图1)。

数据输入包括:

(1)ALUfun:由取指阶段产生的icode和ifun组成,用来规定ALU的计算方式。

(2)ALUB:数据源B,由译码阶段寄存器取出值valB和icode产生。之所以要用到icode,是因为需要告诉ALU当前指令是否是类似push的指令,既要进行数据传输,又要对栈指针进行增减。例如push rax,将rax中的值传送到rsp指向的位置后,还要将rsp中的值-8。

(3)ALUA:数据源A由icode、valA、valB产生。同时需要valA和valC的原因是:有些指令需要先将立即数和其中一个寄存器中的值进行计算,再进行其他计算。例如图3中:rmmovl rA,D(rB)   和  mrmovl D(rB),rA   指令,将D(也就是valC)与rB中的值相加后作为地址,之后该地址中的数据和rA对应寄存器再进行运算。

 

4、访存:

5、写回:

6、更新PC:

 

 

 

 

上一篇:String.format(String format, Object... args)方法详解


下一篇:进程间通讯的7种方式