数字设计与计算机体系结构:第六章

230 阅读17分钟

第六章:体系结构

1.引言

体系结构:程序员所见到的计算机->组成

  • 指令集(汇编语言)
  • 操作空间(寄存器和存储器)
  • 例子:ARM,x86,MIPS,SPARC,PowerPC(他们有不同的语言及寄存器形式)

指令

  • 定义

    • 计算机语言的单词叫指令
  • 两种形式

    • 机器码:计算机只能理解0和1,指令需要被编码为二进制,(32位处理器,指令为32bit)
    • 汇编语言:人类能理解的形式;使用符号来表示指令
    • 汇编语言=>机器码
  • 包括

    • 要完成的操作(+ - 分支 跳转)
    • 操作数(寄存器、存储器、立即数(指令自身))

计算机语言的词汇集叫做指令集:计算机硬件能够实现的操作;不同体系结构的指令集像各地方言,而不是不同的语言,都是定义了基础指令,操作数也都来源于寄存器,存储器,指令本身

不同体系结构并未定义底层硬件实现,同一体系结构,可以根据(价格,性能,低功耗)等要求调整硬件实现形式

寄存器、存储器、ALU和其他模块组织成微处理器的方式称为微结构

ARM体系结构设计的4个准则:

  • 规整性支持简单设计

    • 指令包含固定数目的操作数
  • 加快常见功能

    • 多条汇编指令执行复杂操作(RISV精简指令集)

      • ARM
      • MIPS
    • 只包含简单和常用指令

    • 简化硬件(指令操作和指令译码),指令编码中区分不同指令操作的位数较少

    • 复杂指令集(CISV)硬件复杂,指令编码凌乱,复杂指令操作快,但是增加了简单指令的开销

  • 越小的设计越快

    • 仅有16个寄存器
  • 好的设计需要好的折中方法

    • 机器语言的少量格式允许指令之间的规整性,因此允许更简单的译码器硬件,同时还满足不同的指令需求(三种主要格式:数据处理,存储器。分支)变长太复杂,所以少量类别

2.汇编指令

介绍

  • 以人类能看懂的方式表示机器语言
  • 每条指令包括:操作、操作数
  • 操作数:寄存器、存储器、立即数

指令

  • 加法

  • 减法

操作数

  • 来源

    • 寄存器
    • 指令自身
    • 存储器
  • 详细介绍三种来源

    • 寄存器

      • SARM阵列构造(静态RAM,锁存器)

      • 访问操作数快,指令执行的快

      • ARM体系结构有16个寄存器,x86有8个寄存器

      • 指令仅在寄存器上运行,先将内存的数加载到寄存器

      • 举例

          - a代表空间别名
        
      • 寄存器集

          - R0|参数值/返回值/临时变量
        
          - R0-R4函数参数,超过4个存栈帧里,R0函数返回值
          - R12临时变量
          - R13(SP)栈指针(进栈减小出栈增大)
          - R14(LR)链接寄存器(跳转发生,保护现场,存储跳转指令下一指令的程序PC地址)
          - R15(PC)程序计数器(要执行的下一条指令,但是由于历史原因,读回的PC值是PC+8后的值)
        
    • 常数/立即数

      • 从指令中获取

      • 例子

    • 存储器

      • 从memory读取数据到register

        • LDR
      • 把reg的数据存储到memory

        • STR
      • ARM字节可寻址,一个字包括4字节,故每个字的地址均为4的倍数,高有效自己在左侧,低有效字节在右侧,地址从下向上生长增大(小端)

      • 字节可寻址存储器的组织方式有大端和小端两种格式,子地址相同,只是字节地址顺序不同,大端从高有效字节开始,小端从低有效字节开始

      • 寻址方式

        • 扩展索引

          • LDR R3, [R0, R1, LSL #2]

            • R1左移两位+R0=>R0+(R1X4)
        • 偏移量

        • 预索引

        • 后索引

      • 存储器存储字节和字符

        • LDRB(加载字符)(补0扩展到32位)

        • STRB(存储字节)(忽略高字节,只保存低字节)

        • LDRSB(存储有符号字节)(补符号位扩展到32位)

        • 存储Hello!(0x48 65 6C 6C 6F 21 00)

3.编程

数据处理指令(逻辑和算术指令)

  • 逻辑指令

    • AND
    • ORR(OR)
    • EOR(XOR)
    • BIC(位清除) R1 AND(NOT R2)
    • MVN(按位取反)
  • 移位指令

    • LSL(逻辑左移)左移N位=>乘2^N

    • LSR(逻辑右移)(逻辑移位可以提取组合位域)

    • ASR(算术右移)右移N位=>除2^N

    • ROR(右旋)(没有ROL,因可以右旋互补量完成左旋)

    • 例子

  • 乘法指令

    • 32位*32位=64位
    • 结果小于32位的MUL R1, R2, R3
    • 无符号长整型UMULL R1, R2, R3, R4
    • 有符号长整型SMULL
    • MLA
    • SMLAL
    • UMLAL

条件标志

  • 程序每次以相同循序运行会很无聊

    • 根据CPSR寄存器前四位来有条件的执行后续指令

      • N
      • Z
      • C
      • V
    • 指令的cond字段为条件字段:4bits

    • 一般由CMP指令设置状态位,并根据状态位设置条件标志:

分支(跳转)

  • 无条件分支

  • 有条件分支(与条件标志结合)BEQ

  • B(简单分支)

  • BL(分支并链接,用于函数)

条件语句(汇编代码检测条件与高级语言相反)

  • if

    • 条件指令

  • if/else

    • 条件指令

  • switch/case

循环

  • while

  • for(访问内存非常有用)

    • 访问数组

    • 后索引for循环

函数

  • 调用函数

    • 调用函数将参数存在R0~R3中
    • 将返回地址保存在LR寄存器中
    • BL指令跳转到被调用函数
    • R0~R3如果需要保护,必须由调用函数入栈
  • 被调函数

    • 输入参数

      • 保存在R0~R3
    • 输出返回值

      • 保存在R0
    • 将需要保护的寄存器入栈(如果用到R4~R11,LR,必须先入栈才能用)以及SP以上的栈空间不能被改变

  • 函数调用与返回

    • 基本指令

      • BL SIMPLE (将BL指令的下一个指令地址存入LR寄存器(BL地址+4),并将PC寄存器值改为跳转标号处的指令地址)指令中的立即数为相对于PC+8的指令地址的个数
      • MOV PC LR(返回执行指令的地址)
    • 简单例子

      • LR(0x00008024=PC-4)跳转到0x000902C执行这条指令(PC+8+立即数*4=>LSL 2=0x000902C)
      • 流水线机制导致PC值+8,三级流水线,指令在执行时,PC已经将两个周期后的指令取出来了,故是相对于PC+8
  • 带输入参数和返回值

    • 参数依次存入R0~R3,存不下的放入栈中

    • 返回值存入R0

    • 例子

    • 存储局部变量的存储单元

    • 每个函数有自己的栈帧

    • 函数执行完毕,栈要回收

    • 后进先出

    • 栈是向下生长的,SP(R13)要减去需要的存储空间地址个数,相当于开辟栈空间,再将变量入栈

    • 保存受保护寄存器步骤

      • 创建栈空间来存储一个或多个寄存器的值
      • 将寄存器的值存储在栈中
      • 使用寄存器执行函数
      • 从栈中恢复寄存器的原始值
      • 回收栈空间
    • 例子

    • 代码

        - 
      
    • 保存和恢复多个寄存器

    • LDM与STM分为4种形式

      • 满的降序(FD)=PUSH=STMFD SP! {regs}
      • 空的降序(ED)=POP=LDMFD SP! {regs}
      • 满的升序(FA)
      • 空的升序(EA)
  • 受保护和不受保护寄存器的

    • 受保护寄存器(被调用者保存的)
    • 不受保护寄存器(调用者保存的)
  • 非叶子函数调用

    • 不用调用其他函数的函数称为叶子函数

    • 调用其他函数的函数称为非叶子函数

      • 调用函数规则

        • 必须保存调用后所需的所需的任何不受保护的寄存器(R0~R3,R12),调用后必须恢复这些寄存器
      • 被调用函数规则

        • 保存受保护的寄存器(R4~R11和LR)
      • 例子

          - 
        
  • 递归函数

    • 自己调用自己

      • 例子

        • 栈情况

  • 附加参数和局部变量

    • 调用函数开辟栈帧保存多于四个的其他参数
    • 被调用函数此时可以方位调用函数的栈帧
    • 栈帧中可以保存寄存器R0~R12,LR,局部变量和数组

4.机器语言

简介

  • 主要的三种指令格式

    • 数据处理

      • 第一源:源寄存器

      • 第二源:

        • 立即数

        • 寄存器

          • 移位的
      • 目的寄存器

    • 存储器

      • 三操作数

        • 基址寄存器
        • 立即数或可选移位寄存器存储的偏移量
        • LDR的目标操作数,STR的源操作数寄存器
    • 分支

      • 24位立即数分支偏移量

数据处理命令

  • 六个字段

    • cond(条件编码,无条件默认1110)

    • op(操作码)

      • 数据处理00
      • 存储器01
      • 分支10
    • funct(功能码)

      • I

        • Src2是否是立即数
      • cmd

        • 特定的数据处理指令
      • S

        • 指令是否设置条件标志,是1
    • Rn(第一源寄存器)

    • Rd(目标寄存器)

    • Src2(第二源寄存器)

      • 三种变体

        • 立即数
        • 可选移常数位的寄存器Rm
        • Rs寄存器指定移位数的Rm寄存器
  • 例子

  • 汇编=>机器语言

    • 先看属于什么类型确定op,是否条件指令确定cond与S,什么指令确定cmd,根据操作数类型确定其他位I,Src2等

    • 循环移位rot*2位产生立即数

  • 几个例子

存储器指令

  • 六个字段

    • cond(条件编码,无条件默认1110)

    • op(操作码)

      • 数据处理00
      • 存储器01
      • 分支10
    • funct(功能码)

      • I'

        • Src2是否是立即数
      • U

        • 加减指令
      • P

        • 预索引
      • W

        • 写回
      • B

        • 字节
      • L

        • 加载
    • Rn(基址寄存器)

    • Rd(LDR目标寄存器,STR源寄存器)

    • Src2(偏移量)

      • 两种变体

        • 立即数
        • 可选移常数位的寄存器Rm
    • 字段说明图

    • 例子

分支指令

  • 四个字段

    • cond

    • op=10

    • 1L

      • BL=1
      • B=0
    • 立即数24位

      • 24位二进制补码用于指定相对于PC+8的指令地址
    • 字段说明图

    • 例子

        - 0x80B4-0x80A8=3故IMM24=3
      

寻址模式

  • 寄存器

    • 仅寄存器
    • 立即数移位的寄存器
    • 寄存器移位的寄存器
  • 立即数

  • 基址

    • 立即数偏移量
    • 寄存器偏移量
    • 立即数移位的寄存器偏移量
  • PC相对寻址

    • 相对PC+8+偏移量的地址寻址

解释机器语言代码

  • 先看27:26找到op,再看funct字段

程序存储

  • 机器语言编写的程序是一个32位数序列,这些指令存放在存储器中,这就是程序存储

  • 程序提供通用计算能力,而不是特定的硬件。

  • 程序存储中的指令从存储器中找到或取出,然后由处理器执行,

  • 处理器从存储器中顺序地读出指令->用数字电路硬件译码和执行,当前指令地址存在PC(R15)寄存器中

  • 微处理器的体系结构状态

    • 寄存器文件
    • 状态寄存器

5.编译、汇编与加载

流程

内存映射

  • 地址空间2^3字节=4GB,字地址是4的倍数为0~0xFFFFFFFC

  • ARM地址空间划分为5个部分

    • 文本段(只读段)

      • 代码
      • 文字常量
      • 只读数据
    • 全局数据段(读写段)

      • 存放全局变量

        • 静态基址寄存器访问全局变量,通常使用R9作为静态基指针
    • 动态数据段

      • 栈顶部向下生长
      • 堆底部向上生长
    • 异常处理程序

      • 最底部存储异常向量表
      • 异常处理程序
    • 操作系统OS和输入输出段

      • 最高部分
    • 示意图

编译、汇编

  • GCC

    • 例子

汇编

- 

链接

  • 例子

加载

  • 例子

6.其他主题

加载文字常量例如 int a=0x2B9056F

  • 两种形式的加载

    • LDR Rd,=文字常量
    • LDR Rd, =label标签
  • 例子

      - 0x44=0x815C-(0x8110+8)
    

NOP

  • 伪指令=no op
  • 汇编程序将其转换为=>MOV R0,R0(0xE1A00000)
  • 实现延迟或对齐指令是有用的

异常

  • 异常就是,没有经过调用,就自动调用了

    • 硬件

      • 硬件键盘IO异常叫做中断
      • 重置 reset或读取不存在的内存
    • 软件(陷阱)

      • 错误条件
      • 未定义的指令
      • 重要的形式:系统调用=调用高权限级别程序OS中的函数
  • 执行模式和权限级别

    • 特权级别

      • PL0

        • 用户模式

          • 不能访问存储器受保护部分
          • 例如:操作系统代码
      • PL1

        • 监视
        • 终止
        • 未定义
        • 中断(IRQ)
        • 快速中断(FIQ)
  • 异常向量表

    • 发生异常->处理器根据异常原因跳转到异常向量表->执行处理异常的代码->退出返回用户的代码
  • 备份寄存器

    • 异常更改PC寄存器之前需要将返回地址保存在LR寄存器
    • 每个执行模式都需要LR寄存器,故需要一组寄存器充当每个模式下的LR寄存器
    • 同理需要一组状态寄存器SPSR保存CPSR副本
    • 每个执行模式有自己的堆栈及SP指针存储副本寄存器
    • 在启动之前时需要初始化堆栈和库存版本
  • 异常处理

    • 第一件事将寄存器入堆栈

    • 异常期间流程

      • 1.将CPSR存储到被保存的一组SPSR
      • 2.根据异常类型设置执行模式和权限级别
      • 3.在CPSR中设置中断屏蔽位,以便不会中断异常处理程序
      • 4.将返回地址存储到保存的LR
      • 5.根据异常类型跳转到异常向量表
    • 异常向量表存的是异常处理程序的入口地址

    • 处理程序:

      • 寄存器入堆栈

      • 处理异常

      • 出栈

      • 返回

        • MOVS PC LR(MOVS执行)

          • 1.将存储的SPSR恢复到CPSR
          • 2.复制存储的LR(可能有例外)到PC来返回发生异常的程序
          • 3.恢复执行模式和权限级别(CPSR4:0)
  • 异常相关指令

    • 程序在低级别运行

    • 操作系统在高级别运行

    • 操作系统和高级别PL1执行模式

      • 可使用

        • MRS(从特殊寄存器移动到寄存器)
        • MSR(从寄存器移动到特殊寄存器)
      • 例子

        • 引导时->操作系统可使用这些指令初始化异常处理程序的堆栈
  • 启动

    • 管理员模式->执行引导和加载程序代码

      • 配置内存系统

      • 初始化堆栈指针

      • 从磁盘读取操作系统

        • 二级启动

          • 加载程序(更改为非特权用户模式)

            • 跳转到程序的开头

7.ARM体系结构的演变

发展

  • 26位总线ARMv2
  • 32位ARMv4现代处理器核心
  • ARMv4T加入Thumb 16位指令集提高代码密度
  • ARMv6添加了多媒体指令并增强了Thumb指令集
  • ARMv7改进了浮点和多媒体指令
  • ARMv8引入了全新64位体系结构

Thumb指令集

  • 16位,指令功能较弱-同功能需要更多条指令

  • 约为ARM指令总长的0.65

  • 由ISETSTATE寄存器的T位指示处理器模式:0正常,1:Thumb

  • 指令更复杂不规则

  • Cortex-M系列处理器仅在Thumb状态下运行

  • 例子

DSP指令

  • 增加了许多指令乘法累加(MAC)...

  • 数据类型

  • 指令一般在短16位数据上操作

  • 乘法累加指令

      - 
    
  • 各种数据类型的乘法和MAC代码

      - 
    
  • 浮点指令

  • 节能和安全指令

    • ARMv6支持睡眠模式
    • ARMv7增强了异常处理方式以支持虚拟化和安全性
    • 虚拟模式多个操作系统并行
    • 管理程序以PL2特权级别在操作系统之间切换
    • 有一个安全状态->有限的进入方式和对存储器安全部份的受限访问
    • 即使攻击者危及操作系统,安全内核也可能抵制篡改
  • SIMD(单指令多数据)指令(压缩算术)

    • V开头

    • 类型

      • 同样为浮点指令定义的基本算数函数
      • 多个元素的加载和存储,包括去交错和交错
      • 按位逻辑运算
      • 比较
      • 使用和不使用包和运算的各种种类的移位、加法和减法
      • 各种乘法和MAC
      • 杂项指令
    • 例子

      • VADD.I8 D2,D1,D0 D64位,8*8打包
      • VADD.I32 Q2,Q1,Q0 Q128位,32*4打包

64位体系结构

  • ARMv8指令仍然是32位长,指令集非常像ARMv7,消除了某些问题
  • 寄存器文件扩展为31个64位寄存器(X0~X30)
  • PC和SP不再是通用寄存器的一部分。链接寄存器LR=X30,没有X31寄存器它被称为零寄存器(ZR)硬连线至0
  • 数据处理指令可以在32位和64位值上运行,而加载和存储始终使用64位地址
  • 大多数指令删除了条件字段,为了腾出空间来指定源目寄存器
  • 分支指令仍然是有条件的
  • ARMv8还简化了异常处理,使高级SIMD寄存器的数量增加了一倍,并添加了AES和SHA加密指令。指令编码相当复杂
  • 复位时,ARMv8处理器以64位模式启动,通过在系统寄存器中置位一个位并调用异常,处理器可以进入32位模式。异常返回时,他返回64位模式

8.另一个视角:x86体系结构

x86体系结构

  • 个人PC都是X86

  • CISC复杂指令集

  • 变长指令集

  • 译码硬件复杂

  • 主要差异

x86寄存器

  • 8个16位寄存器

    • 大部分为通用寄存器
  • 一些寄存器可独立存取高8位和低8位字节

  • 32位产生后寄存器也被扩展为32位

    • EAX

      • 通用寄存器
    • EBX

      • 通用寄存器
    • ECX

      • 通用寄存器
    • EDX

      • 通用寄存器
    • ESP

      • 栈指针
    • EBP

      • 基址指针
    • ESI

      • 源寄存器
    • EDI

      • 目的寄存器
    • EIP

      • 程序计数器
    • EFLAGS

      • 状态标志寄存器

x86操作数

  • 立即数

  • 寄存器

  • 内存

  • 只有两个操作数

    • 操作数位置组合(除了内存到内存随意组合)

  • 寻址方式

  • 可对8位16位数据操作

状态标志

  • 使用状态标志(条件吗)判断分支跳转以及保存进位和算术溢出标志

  • 使用EFLAGS32位寄存器存储状态标志

  • 一些位给出,另一些位用于操作系统

x86指令集

  • x86指令集比ARM指令集大

      - 
    
    • 条件跳转指令

x86指令编码

  • 复杂

x86的其他特征性

  • 将内存分段

    • 每段不大于64KB
  • 各种前缀:

    • 0x66用于选择16位或32位操作数
    • 锁定总线
    • 预测分支是否执行
    • 字符串移动中重复执行指令
  • 有些指令比简单指令组合慢要避免使用:例如整个字符串操作

整体情况

  • x86更倾向于更加短小的程序代码
  • 大杂烩

9.总结

要指挥一台计算机必须要说计算机的语言

计算机体系结构定义了如何指挥一个处理器

了解一个新的体系结构需要了解

  • 数据的字长是多少位
  • 寄存器如何组织
  • 内存时怎样组织的
  • 指令是怎样的

定义体系结构的威力在:针对特定体系结构写出的程序可以运行在这种体系结构的不同硬件实现上

图片思维导图

第六章:体系结构.png