《嵌入式C语言自我修养:从芯片、编译器到操作系统》学习笔记
ARM体系结构
计算机指令集:
复杂指令集(CISC)、精简指令集(RISC)(嵌入式中较为常见)、显式并行指令集(EPIC)和超长指令字指令集(VLIW)。
ARM处理器的多种工作模式
用户模式:应用程序正常运行时处于用户模式,用户模式属于普通模式,有些特权指令无法运行。
特权模式:发生中断程序会切换到特权模式。在ARM处理器中除用户模式剩下的都是特权模式。
ARM寄存器
寄存器可分为通用寄存器和专用寄存器。
通用寄存器:
R0~R12属于通用寄存器,除FIQ工作模式下这些寄存器都是共用、共享。
R0~R3:用于传递函数参数。哈哈,是不是有一种恍然大悟的感觉,这就是为啥很多编程规范说,函数形参不建议超过4个。为啥有这个规定呢?根因是ATPCS规则,后面介绍。
R4~R11:保存程序运算的中间结果和函数局部变量。
R12:常用来作为函数调用过程的临时寄存器。
专用寄存器:
R13:又称堆栈指针寄存器(Stack Pointer,SP,这个比较常见)。用于维护和管理寄存器调用过程中的栈帧变化。R13总是指向当前正在运行的栈帧。
R14:又称为链接寄存器(Link Register,LR,这个比较常见)函数调用过程中用于保护上一级函数调用的返回地址。看到这里有些啥想法吗?如果程序死机是不是可以通过查找LR寄存器来定位问题?
R15:又称程序计数器(Program Counter,PC,这个比较常见)。CPU从内存中取指令执行就是默认从PC保存的地址中取。PC指针的值是当前指令地址+8。
CPSR(Current Processor State Register):用于表征当前处理器的运行状态。
每一种工作模式都有一个单独的CPSR寄存器。
FIQ模式比较特殊,为快速响应中断,减少中断现场保护带来的时间开销,在FIQ模式下ARM处理器会处理独享的R8-R12寄存器。
ARM汇编指令
ARM处理器属于冯.诺伊曼架构,程序和数据都在同一个存储器上,内存空间和IO口空间统一编址,ARM处理器对程序指令、数据、IO空间外设寄存器的访问都要通过Load/Store指令来实现。
递减栈:栈指针从高地址向低地址移动。
递增栈:栈指针从低地址向高地址移动
ATPCS规则
ATPCS的全称是ARM-Thumb Procedure Call Standard,核心内容定义了ARM子程序调用的基本规则及堆栈的使用。
● 子程序间要通过寄存器R0~R3(可记作a0~a3)传递参数,当参数个数大于4时,剩余的参数使用堆栈来传递。函数形参不建议超过四个,大于4个运行效率会慢,根因在这里。
● 子程序通过R0~R1返回结果。
● 子程序中使用R4~R11(可记作v1~v8)来保存局部变量。
● R12作为调用过程中的临时寄存器,一般用来保存函数的栈帧基址,记作FP。
● R13作为堆栈指针寄存器,一般记作SP。
● R14作为链接寄存器,用来保存函数调用者的返回地址,记作LR。
● R15作为程序计数器,总是指向当前正在运行的指令,记作PC。
重新认识编译器
一套完整的工具集主要包括以下几部分:
● 编译器:用来将C源文件编译成汇编文件。
● 汇编器:用来将汇编文件汇编成目标文件。
● 链接器:用来将目标文件组装成可执行文件。
● 二进制转化工具:objdump、objcopy、strip等。
● 库打包工具:ar。
● 调试工具:gdb、nm。
● 库/头文件:根据C语言标准定义的API实现的C标准库及对应的头文件。