IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 嵌入式 -> CSAPP|chapter04|处理器体系架构 -> 正文阅读

[嵌入式]CSAPP|chapter04|处理器体系架构

4.处理器体系架构|

指令集"Y86-64"

4.1程序员可见的状态

在这里插入图片描述
RF:程序寄存器
CC:条件码
Start:程序状态(程序的执行状态)
PC:程序计数器
DMEM:内存

15个64位内存的程序寄存器
Y86-64 相比x86,省略了%r16
特别的:%rsp:栈指针

movq:rrmovq、irmovq、rmmovq和 mrmovq

movq前两个字母表示了源和目的格式

irmovq
源操作数是立即数(Immediate
目的操作数是寄存器(register)
rrmovq
源操作数是寄存器(register)
目的操作数是寄存器(register)
rmmovq
源操作数是寄存器(register)
目的操作数是内存(memory)
mrmovq
源操作数是内存(memory)
目的操作数是寄存器(register)

对上面数据传送指令进行编码
在这里插入图片描述
上图中每条指令第一个字节(8bit)(前两位)表明指令的类型,这个字节分为两部分,每部分占(4bit),高四位(4bit)表示指令代码,低四位(4bit)表示指令功能

下面为了方便给寄存器进行编号
在这里插入图片描述

寄存器编号(0-14)

0 %rax
1 %rcx
2 %rdx
3 %rbx
4 %rsp
5 %rbp
6 %rsi
7 %rdi
8 %r8
9 %r9
A %r10
B %r11
C %r12
D %r13
E %r14
F 五寄存器

irmovq,该指令的指令代码为3,指令功能为0
在这里插入图片描述
由于源操作数是立即数,因此用0xF进行填充

4.1.1 四条整数操作

对于整数的操作,我们定义了四条整数操作指令,和x86-64不同,我们定义的指令只允许对寄存器中的数据进行操作

在这里插入图片描述
以上四条指令属于同一类型,指令代码是一样的,不同的是指令的功能

Opq rA,rB 6|fn|rA|rB
addq 6|0
subq 6|1
andq 6|2
xorq 6|3

以上四条指令属于同一类型,因此指令代码是一样的,不同的是指令的功能

4.1.2 七条跳转指令

对于跳转,我们定义了7条跳转指令,它们的跳转条件和x86-64中的跳转指令相同,都是根据条件码的某种组合来判断是否进行跳转

jxx Dest

jmp 7|0
jle 7|1
jl 7|2
je 7|3
jne 7|4
jge 7|5
jg 7|6


JMP Label 1 直接跳转
JMP *Operand 1 间接跳转
JE Label JZ ZF 相等
JNE Label JNZ ~ZF 不相等
JS Label SF 负数
JNS Label ~SF 非负数

JG JNL 大于(有符号>)
JGE JNLE 大于等于(有符号)
JL JNG 小于(有符号)
JLE JNGE 小于等于(有符号)
JA JNB 大于(无符号)
JAE JNBE 大于等于(无符号)
JB JNA 小于(无符号)
JBE JNAE 小于等于(无符号)

在这里插入图片描述

4.1.3 六条数据传送指令

rrcomvq有相同的指令格式,只有条件码满足条件时才会更新目的寄存器的值

comve	S,R			相等
cmovne	S,R			不相等/非零
cmovs	S,R			负数
cmovns	S,R			非负数
cmovg	S,R			大于(有符号)
cmovge	S,R			大于等于(有符号)
cmovl	S,R			小于(有符号)
cmovle	S,R			小于等于(有符号)
cmova	S,R			大于(无符号)
cmovae	S,R			大于等于(无符号)
cmovb	S,R			小于(无符号)
cmovbe	S,R			小于等于(无符号)

cmovxx rA,rB
rrmovq 2|0
comvle 2|1
comvl 2|2
cmove 2|3
cmovne 2|4
cmovge 2|5
cmovg 2|6
在这里插入图片描述

系统操作指令
halt 0 0
nop 1 0
call Dest 8 0 Dest
ret 9 0
pushq rA A 0 rA F
popq rA B 0 rA F

在这里插入图片描述

指令编码

在上面的操作指令中

  • halt指令停止指令的执行,执行该指令会导致处理器停止,并将状态码设置为HLT
  • nop 指令表示一个空操作
  • call 和ret指令分别实现函数的调用和返回
  • push 和pop 指令分别实现入栈和出栈的操作

指令编码
rmmovq %rsp,0x123456789abcd(%rdx)

rmmovq
源操作数是寄存器(register)
目的操作数是内存(memory)

根据前面rmmovq指令的编码定义,该指令二进制表示第一个字节为0x40;
指令操作数部分的寄存器%rsp对应的寄存器编号为0x4,基址寄存器rdx对应的编号为0x2
该指令二进制表示中的第二个字节为0x42

指令编码中偏移量占8个字节,因此我们需要在该偏移量前面补0来凑齐8个字节。
又由于我们采用小端法存储,因此我们还要对偏移量进行字节反序操作。最终我们得到该指令的二进制表示如下

40 42 cd ab 89 67 45 23 01 00

Y86-64的状态码
名字含义
1AOK正常操作
2HLT遇到halt指令
3ADR遇到非法地址
4INS遇到非法指令

Y86-64中c语言的汇编翻译

long sum(long *start,long count){
long sum=0;
while(count){
sum+=*start;
start ++;
count --;
}
return sum;
}
gcc -Og -S sum.c

得到

在这里插入图片描述

在这里插入图片描述
c语言代码的作用是计算一个数组的元素之和。其中指针start指向数组的起始位置,count用于表示数组的长度
可以看到,除了数据传送指令之外,Y86-64指令与x86-64的指令相差不大

看看上面的汇编代码是如何翻译成二进制指令的
在这里插入图片描述

阶段的概念

处理器在执行单条指令的时候,往往也包含着很多操作
过程组织成下面6个阶段


  1. 取址

处理器执行的所有指令都需要取址
在Y86-64指令系统中,指令的长度不是固定的,因此取址阶段需要根据指令代码判断指令是否含有寄存器指示符、是否含有常数来计算当前的指令长度

  1. 译码

译码阶段中,处理器从寄存器文件中读取数据,寄存器文件有两个端口,可以支持同时进行两个读操作

  1. 执行

指令被正式执行的阶段,在该阶段中,算术逻辑单元(ALU)主要执行三类操作,执行算术逻辑单元,计算内存引用的有效地址,针对push和pop指令的运算

  1. 访存

内存进行读写操作的阶段

  1. 写回

执行结果写回到寄存器文件中

  1. 更新

PC更新为下一条指令的地址


subq指令的各个阶段

在这里插入图片描述
看看上面这条subq指令各阶段包含的内容

在这里插入图片描述
如上图所示

  1. 取址阶段,根据指令代码来计算指令长度。
  2. 译码阶段,根据寄存器指示符来读取寄存器的值。
  3. 执行阶段,ALU 根据译码阶段读取到的操作数以及指令来执行具体的运算,并设置条件码寄存器
  4. 访存阶段,由于减法指令不需要读写内存,因此该阶段无操作。
  5. 写回阶段,将 ALU 的运算结果写回寄存器
  6. 更新阶段,更新程序计数器

imovq指令的各个阶段

imovq指令的各个阶段
irmovq $8,%rsp
在这里插入图片描述

在这里插入图片描述
如前图所示

  1. 取址阶段,该指令既含有寄存器指示符字节,也含有常数字段。
  2. 译码阶段,该指令不需要从寄存器中读取数据,译码阶段无操作。(源是立即数$8)
  3. 执行阶段,虽然该指令仅仅传送数据,看似不需要 ALU,但由于 ALU 的输出端与寄存器的写入端相连,数据的传送还是需要经过 ALU,因此该指令将立即数加 0.
  4. 访存阶段,该指令不需要读写内存,因此该阶段无操作。
  5. 写回阶段,将 ALU 的运算结果写回寄存器。
  6. 更新阶段,更新程序计数器。
rrmovq指令的各个阶段

如前图所示

  1. 取址阶段,该指令既含有寄存器指示符字节,也含有常数字段。
  2. 译码阶段,从寄存器中读取数据
  3. 执行阶段,ALU 根据偏移量基址寄存器来计算访存地址。
  4. 访存阶段,将寄存器 rsp 的数值写入内存中。
  5. 写回阶段,由于内存地址由执行阶段得出并写入寄存器,因此写回阶段不需要进行操作。
  6. 更新阶段,更新程序计数器。
pushq指令的各个阶段

pushq %rdx | a| 0 |2| f|
在这里插入图片描述
上面这条pushq指令各阶段的内容如下
在这里插入图片描述

  1. 取址阶段,该指令含有寄存器指示符,不含常数,因此指令长度为2字节。

  2. 译码阶段,由于 pushq 指令要将寄存器 rdx 的值保存到栈上,因此该指令不仅需要读取寄存器 rdx 的值,还需要读取寄存器 rsp 的值。

  3. 执行阶段,ALU 计算内存地址

  4. 访存阶段,将寄存器 rdx 的值写到上。

  5. 写回阶段,由于寄存器 rsp 指向的内存地址发生了变化,因此更新寄存器rsp的值。

  6. 更新阶段,更新程序计数器。

je指令的各个阶段

在这里插入图片描述
上图阶段内容如下
在这里插入图片描述

  1. 取址阶段,该指令含有常数字段,不含寄存器指示符字节,因此指令长度为 9字节。
  2. 译码阶段,不需要读取寄存器,无操作。
Cond的引入

在这里插入图片描述

  1. 执行阶段,标号为Cond 的硬件单元根据条件码指令功能来判断是否执行跳转,该模块产生一个信号Cnd,若Cnd=1,则执行跳转;Cnd = 0 则不执行跳转。
  2. 访存阶段,无操作。
  3. 写回阶段,无操作。
  4. 更新阶段,若 Cnd = 1,将 PC 的值设为0x040;若 Cnd = 0,则将 PC 的值设为当前值加 9。

4.处理器体系架构||

取地址的硬件设计

  1. 在取址阶段中,取址操作一程序计数器PC的值作为起始地址

  2. 由于Y86-64指令集中最长的指令占10字节,取址操作每次从指令内存读取10个字节

  3. 10字节分为两部分

    • 第一部分占1字节
    • 第二部分占9字节
    • 例如编码为 30 |f8 08 00 00 00 00 00 00 00 的指令,将被分为30和f008----
Split硬件单元处理第一部分(1Byte)

Split的硬件单元处理第一部分,它将这个字节分成两部分,每部分占4个比特位,使这个字节分为两个字段,分别为指令代码指令功能。用icode和ifun 表示

根据icode可以确定当前指令的状态信息,例如指令的合法性,如果icode在0x0到0xB之间,那么它就是一条合法指令,此外通过icode可以判断当前指令是否包含寄存器指示符字节常数字节

通过前面说过的判断结果就可以计算出当前指令的长度,例如一个指令既含寄存器指示符字节,又含常数字节,那它的长度就是10字节,如果既不含寄存器指示符字节,又不含常数字节,它的长度就是1字节

可以通过PC值加上当前的指令长度来计算内存中下一条指令的地址,用于后续的更新阶段

Align硬件单元处理第二部分

Align来产生寄存器字段常数字段,该硬件单元通过信号need_regids来判断该指令是否包含寄存器指示符字节

  • 若need_regids =1,说明该指令包含寄存器指示符字节,那么第一个字节将被分成两个部分,每个部分占4个bit,然后分别装入寄存器指示符rA和rB中。
  • 若need_regids=0,说明该指令不包含寄存器指示符字节,此时rA,rB这两个字段设置为0xF

此外,若该指令含有常数,Align单元还将产生常数字段 valC
当need_regids=1时,valC被设为指令的第2~9字节
当need_regids=0时,valC被设为指令的1~8字节

译码阶段的硬件设计
  1. 译码阶段的操作是从寄存器文件中读取数据,在Y86-64处理器中寄存器文件有两个读端口,它支持同时进行两个读操作
    两个读端口的地址输入为
    srcA,srcB
    从寄存器文件读取的数值通过valA和valB输出

  2. 读端口的srcA和srcB用于产生寄存器的ID
    这需要寄存器指示符rA以及rB

  3. 由于某些指令例如push指令,该指令的寄存器指示符只含有目的寄存器ID,但执行压栈操作的时候,还需要获得栈顶指针 rsp的值,因此srcA和srcB不仅需要传入rA和rB,还需要指令代码 icode

执行阶段的硬件设计

执行阶段的核心部件ALU根据指令功能 ifun来判断对输入的操作数进行何种运算。每次运行的时候,ALU都会产生三个与条件码相关的信号,零,符号,溢出

我们只希望ALU在执行算术逻辑指令时才设置条件码。而计算内存引用地址以及栈操作的时候不要设置条件码。因此我们使用Set_CC信号根据指令代码icode来控制是否需要设置条件码

在这里插入图片描述

此外,我们使用名为Cond的硬件单元来控制跳转操作。Cond会根据指令功能和条件码寄存器来产生Cnd信号
对于跳转指令,如果Cnd=1 跳转
Cnd=0不跳转

访问阶段的硬件设计

四个控制块

  1. 读控制块
    用于进行读操作
  2. 写控制块
    用于进行写操作
  3. 内存地址控制块
    用于产生内存地址
  4. 数据输入控制块
    用于输入数据

访存阶段的最后还将根据icode判断出指令的有效性以及内存状况产生instr_validimem_error 信号来计算状态码

写回阶段的硬件设计

首先为寄存器文件添加M和E,这两个写端口,对应的地址输入为dstE和dstM,需要注意的是,当执行条件传送指令 cmov时,写入操作还要根据执行阶段计算出的cnd信号,当条件不满足时候,以目的寄存器设置为0xF来禁止写入寄存器文件

更新阶段的硬件设计

更新阶段PC的值有以下三种情况

  1. call PC=call指令的常数字段
  2. ret PC=ret在访存阶段从内存中读取的返回地址
  3. jxx
    满足跳转条件cnd=1,新的PC的值等于跳转指令的常数字段
    不满足跳转条件,cnd=0,新的PC值等于当前PC值加上当前指令长度
  4. 数据输入控制块,用于输入数据
  嵌入式 最新文章
基于高精度单片机开发红外测温仪方案
89C51单片机与DAC0832
基于51单片机宠物自动投料喂食器控制系统仿
《痞子衡嵌入式半月刊》 第 68 期
多思计组实验实验七 简单模型机实验
CSC7720
启明智显分享| ESP32学习笔记参考--PWM(脉冲
STM32初探
STM32 总结
【STM32】CubeMX例程四---定时器中断(附工
上一篇文章      下一篇文章      查看所有文章
加:2021-12-24 18:38:44  更:2021-12-24 18:38:56 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/26 14:34:29-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码