指令集架构
指令集
说明了操作种类、指令格式(操作码和地址码,地址码个数,操作码定长与拓展)、寻址方式、地址空间大小和寄存器个数等。简单可以理解为汇编指令用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位
- Intel 80386是第一款i386 CPU(第一款IA-32架构的CPU)
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-64
或x86_64
称呼此64
位架构。甲骨文公司及Microsoft
称之为x64
。BSD
家族及其他Linux
发行版则使用amd64
,32
位版本则称为i386
(或i486/586/686
),Arch Linux
用x86_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核为基础进行设计,可以缩短设计所需的周期。
参考:
指令集架构:
- ARMv1~ARMv9(可以有一定的变种比如ARMv8-A)
- ARMv8是首款64位的ARM指令集
处理器架构
- ARMv3~ARMv6:
- ARM6, ARM7, ARM9, ARM11系列
- ARMv7及以后
- Cortex-A:大型嵌入式系统(手机)
- Cortex-R:实时处理器
- Cortex-M:单片机
- ARMv3~ARMv6:
参考:
参考:
Android
简介
Android是一个开源的,基于Linux的移动设备操作系统,主要使用于移动设备
谷歌在2007年发布了第一个测试版本的 Android 软件开发工具包(SDK),第一个商业版本的 Android 1.0,则发布于2008年9月。
Android 应用程序一般使用 Android 软件开发工具包,采用 Java 语言来开发。
版本
Android版本(版本代号)
- 每个Android 版本对应一个Android SDK,可以类比JDK
Android API版本:有利于设置和解决兼容性问题
Android NKD
工具链
背景:
- 使用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
清除中间文件,重新构建