指令集架构

指令集

说明了操作种类、指令格式(操作码和地址码,地址码个数,操作码定长与拓展)、寻址方式、地址空间大小和寄存器个数等。简单可以理解为汇编指令用01表示。

CPU位数=CPU中寄存器的位数=数据总线宽度

  • 硬件厂商开发某种指令集的CPU,需要该指令集专利持有者进行授权

    • 比如ARM公司自己的研发指令集叫ARM指令集,对外授权(同时ARM公司还进行微架构的授权)

    • 一些大型公司都获得ARM公司针对ARM指令集的授权,开发兼容ARM指令集的不同的微架构

      • 比如Intel授权AMD可以生产兼容x86指令集的CPU
  • 编译:高级语言翻译成特定ISA的机器码

  • 参考

复杂指令集CISC

  • x86:在1978年的Intel 8086 CPU(16位)指令集基础上,发展而来的一些列指令集的泛称

    • 桌面级CPU一般都是x86的,兼容8086指令集
  • IA-32(x86,i386):Intel将16位的x86拓展为32位的IA-32,但是由于IA-32的统治地位,x86也一般指IA-32的CPU

    • Intel 80386是第一款i386 CPU(第一款IA-32架构的CPU)
      • i386,i486:即Intel 80386, Intel 80486
      • Pentium(i586):Intel 80586
      • Pentium Pro(Pentium Ⅱ,i686):Intel 80686
    • 此后,x86成为一些列架构的泛称,不限于16位,32位,64位
  • IA-64:1994年Intel推出的与x86完全无关的新架构(也不兼容之),基于显式并行指令运算(EPIC)的64位指令集架构

    • 2001年发布第一款基于IA-64的CPU,叫Itanium安腾,IA-64也称为Intel Itanium
    • 但是由于软件环境的缺乏和AMD的竞争,导致市场不好
  • x86-64(x64):1999年,AMD推出x86-64架构(简称x64),是对IA-32(x86)的兼容和拓展

    • 2003年AMD发布的一款基于x86-64的CPU,x86-64也称为AMD64

    • 后来Intel也用AMD64架构,称为IA-32e(IA-32 extension),后来又叫Intel64

    • x86-64, x64, AMD64, Intel64, IA-32e(IA-32 extension)基本是一个东西

      • 苹果公司和 RPM 包管理员以 x86-64x86_64 称呼此 64 位架构。甲骨文公司及 Microsoft 称之为x64BSD 家族及其他 Linux 发行版则使用 amd6432 位版本则称为i386(或 i486/586/686),Arch Linuxx86_64 称呼此 64 位架构。

        x86,x64,x86-64,amd64,arm指令集架构之间的关系中x86 架构发展

  • 参考

精简指令集RISC

  • ARM
    • ARMv3~ARMv7都是32位
    • ARMv8:向前兼容32位指令,同时
      • AArch64:64位执行状态,使用全新的ARM 64位指令集
      • AArch32:32位执行状态
  • RISC-V:伯克利发明的一种基于RISC的开源指令集架构
  • MIPS
  • PowerPC

微架构

  • 微架构:硬件电路(或CPU单个核心core)的结构和实现
  • CPU研发能力一般指的是独立的微架构研发能力,是否使用自行研发的指令集关系不大
    • 研发兼容的指令集可以没有获得授权,指令集的研发不是很难,但是之后获得授权后才能合法销售
    • 微架构的设计细节是保密且复杂的
    • SoC(System on Chip)封装相对简单
  • 商业模式
    • 之前在PC时代,CPU研发厂商自己的微架构只有自己用
    • 后来在智能设备时代,ARM公司将自己的微架构出售,其他厂商可以拿来组装,比如Cortex系列核心
    • 由于ARM公司的成功,ARM公司针对PC领域发布了ARM v8 64位指令集
      • 以前ARM适合低功耗的场景,随着技术进步,指令集对微架构的影响越来越小
  • 指令集的选择:倾向于选择软件生态良好的指令集
    • 以前获得指令集的授权很困难,主要通过技术交换的形式(指令集多授权一家,就多一个对手)
    • 后来ARM对指令集授权略微放松
  • 参考:

计算机架构

  • 冯.诺伊曼架构:程序和指令存储在一起
  • 哈佛架构:程序和指令分开存储
    • 比如单片机(51单片机,STM32单片机),Cortex-M系列
  • 现代处理器架构一般指令和数据共享存储,但是CPU内部缓存分开

特别介绍:ARM

ARM商业发展

  • 由于商业需要,1985年,Acorn公司基于RISC,自研CPU(包括指令集和微架构),称为ARM(Acorn RISC Machine),型号命名为ARM1(对标80286)

  • 后来,Acorn公司和苹果公司联合成立了一家叫ARM(Advanced RISC Machines)的公司,开启新的产品策略:授权

    传统商业模式:

    • IDM(Integrated Design and Manufacture):从设计,到制造、封装测试以及投向消费市场一条龙全包,比如Intel
    • 无工厂模式Fabless:自己设计,制造交给代工厂,比如AMD,NVIDIA
    • Foundry:只做代工
    • 使用层级授权(处理器授权):只能买来已经封装好的CPU,不能更改原来设计,可以配置的地方不多
    • 内核层级授权(POP授权):以一个内核(或IP核)为基础然后在加上自己的外设
    • 架构层级授权:授权使用ARM指令集,可以修改指令集,但是比较贵
      • 比如华为基于ARMv8,自研达芬奇架构
  • 后来ARM公司越来越成功,苹果公司逐渐卖掉其股份,开发ipod(基于ARM指令集)。

    • 2007年,苹果公司发布iphone,基于ARM指令集
    • 2008年,谷歌发布Android系统,也是基于ARM指令集
  • 2016年,ARM公司被软银集团收购

  • 参考

ARM处理器

一般处理器就是指CPU

但是ARM处理器指的是单个核(或IP核,或内核),因为厂商可以在IP核上进一步封装,最终CPU不尽相同

IP核,全称知识产权核(英语:intellectual property core),是在集成电路的可重用设计方法学中,指某一方提供的、形式为逻辑单元、芯片设计的可重用模组。IP核通常已经通过了设计验证,设计人员以IP核为基础进行设计,可以缩短设计所需的周期。

参考:

参考:

ARM体系架构概述

Android

简介

  • Android是一个开源的,基于Linux的移动设备操作系统,主要使用于移动设备

  • 谷歌在2007年发布了第一个测试版本的 Android 软件开发工具包(SDK),第一个商业版本的 Android 1.0,则发布于2008年9月。

  • Android 应用程序一般使用 Android 软件开发工具包,采用 Java 语言来开发。

版本

工具链

背景:

  • 使用GCC编译,很多时候需要手动链接(只有标准库才默认链接)
  • 当需要链接的文件很多时,一来每次在命令行中写一遍繁琐容易出错,二来无法使用增量编译

Makefile

  • 背景:make命令根据编译规则进行编译,而且可以进行增量编译,makefile用于写编译规则

  • 简要语法:

  • 语法笔记

    • make:即制作出某个指定的文件(默认makefile中第一个文件)

      • 越是接近目标文件的命令,就越是要写在前面。因为程序是按照递归的方式进行依赖文件查找的,看到第一行有一个没见过的依赖文件,就往下一行进行查找,以此类推。
    • 核心概念:目标target,前置条件prerequisite,命令command

    • 伪目标的使用

      • 伪目标是一个命令,且没有前置条件:比如clean,显式使用内置目标名指定为伪目标,主要用于执行命令

      • 伪目标是一个文件,但是前置条件有多个,且没有命令:比如生成多个文件

CMake

  • 背景:
    • 当工程很大的时候,手写Makefile也不简单
    • Makefile与平台相关,无法实现跨平台
  • cmake:跨平台的项目管理工具,自动生成makefile文件,然后make构建
    • 手写CMakeLists.txt文件,cmake生成Makefile,然后再make构建
  • cmake简要语法
    • 指令大小写无关,变量大小写相关

    • 可以使用双引号将文件名或目录名包含其中

    • add_executable:将源文件编译成可执行文件

    • add_library:将源文件编译为库文件

      • 在构建时,静态库和动态库重名会导致后面的构建失败,参考
      • SET_TARGET_PROPERTIES:同时构建同名的静态库和动态库
    • aux_source_directory(<dir> <variable>):将dir目录下所有源文件的文件名存放到variable变量中

    • add_subdirectory:包含一个子目录,该子目录中也有一个CMakeLists.txt文件和代码文件,它们也会被处理,同时可以指定编译输出(包含编译中间结果)的路径

    • link_directories:添加共享库搜索目录

      • CMAKE_LIBRARY_PATH:设置库文件搜索目录,这不是cmake变量(需要在bash中设置),通过FIND_LIBRARY找到相应库文件
    • target_link_libraries(<target> <items>):为库或可执行文件加入库链接

    • include_directories:添加头文件搜索目录

      • CMAKE_INCLUDE_PATH:设置头文件搜索目录,这不是cmake变量(需要在bash中设置),通过find_path找到相应头文件
    • target_include_directories:在编译目标文件时指定头文件

    • find_系列

      • find_package:加载外部库到项目中
    • configure_file:默认定义了一些编译选项的值

    • option:添加编译选项(更准确是代码中的宏定义)

    • 变量

      • 创建变量:set(),获取变量的值:${variable},调用环境变量:$ENV{}
      • 追加变量的值:set(SRC_LIST ${SRC_LIST} test.cpp)
      • PROJECT_NAME
      • PROJECT_BINARY_DIR、CMAKE_BINARY_DIR:编译路径,当前工程的二进制路径(即编译产物会存放到该路径,一般为build所在路径)
      • PROJECT_SOURCE_DIR、CMAKE_SOURCE_DIR:工程根目录,即顶层CMakeLists.txt文件的路径
      • EXECUTABLE_OUTPUT_PATH:编译生成的可执行文件的路径
      • LIBRARY_OUTPUT_PATH:编译生成的共享库文件的路径

最佳实践

项目配置

  • 在源文件同级目录下建立目录build,在build中
    • cmake ..:将cmake得到的中间文件保存在build文件夹中,需要重新构建直接删除文件夹
    • make:构建,可以使用make clean清除中间文件,重新构建