第3章 嵌入式编程基础知识

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/o_rdwr/article/details/82182576

前言

一个C/C++文件要经过预处理(preprocessing)、编译(compilation)、汇编(assembly)和连接(linking)才能变成可执行程序

后缀名 语言种类 后期操作
.c C源程序 预处理、编译、汇编
.C C++源程序 预处理、编译、汇编
.cc C++源程序 预处理、编译、汇编
.cxx C++源程序 预处理、编译、汇编
.m Objective-C源程序 预处理、编译、汇编
.i 预处理后的C文件 编译、汇编
.ii 预处理后的C++文件 编译、汇编
.s 汇编语言源程序 汇编
.S 汇编语言源程序 预处理、汇编
.h 预处理器文件 通常不出现在命令行上

- .o: 目标文件(Object file,OBJ文件)
- .a: 归档库文件(Archive file)

总体选项

参数 说明
-c 预处理、编译和汇编源文件,但是不做连接
-S 编译后即停止,不进行汇编
-E 预处理后即停止
-o 制定输出文件名
-v 显示制作GCC工具自身时的配置命令

连接器选项

参数 说明
object-file-name 如果某些文件没有特别明确的后缀,就认为它们是OBJ文件或库文件
-llibrary 连接名为library的库文件
-nostartfiles 不连接启动标准启动文件,标准库文件仍然正常使用
-nostdlib 不连接系统标准启动文件和标准库文件,只把制定的文件传递给连接器
-static 在支持动态连接的系统上阻止连接共享库
-shared 生成一个共享OBJ文件,可以和其它OBJ文件连接产生可执行文件
-Xlinker option 把选项option传递给连接器。可以用来传递系统特定的连接选项,GCC无法识别这些选项。如果需要传递携带参数的选项,必须使用两次”-Xlinker”,一次传递选项,另一次传递其参数
-Wl, option 把选项option传递给连接器。如果option中含有逗号,就在逗号处分割成多个选项。
-u 使连接器认为取消了symbol的符号定义,从而连接库模块以取得定义

连接脚本

  • ALIGN(align):指定对齐的要求

  • AT(ldadr):指定这个段在编译出来的映像文件中的地址——加载地址。如果不使用这个选项,则加载地址等于运行地址

Objcopy

参数 说明
input-file、outfile 如果未指定outfile文件,将生产文件覆盖为input-file
-I bfdname 指明源文件的格式
-O bfdname 使用指定的格式来输出文件
-F bfdname 同时指明源文件、目的文件的格式
-R sectionname 从输出文件中删除所有名为sectionname的段
-S或–strip-all 不从源文件中复制重定位信息和符号信息到目标文件中
-g或–strip-debug 不从源文件中复制调试符号到目标文件中

Objdump

参数 说明
-b bfdname 指定目标码格式
-d 反汇编可执行段
-D 反汇编所有段
-EB或-EL 指定字节序
-f 显示文件的整体头部摘要信息
-h 显示目标文件各个段的头部摘要信息
-i 显示支持的目标文件格式和CPU架构
-j name 仅显示指定section的信息
-m machine 指定反汇编目标文件时使用的架构

寄存器列表和内存单元对应关系

  1. 编号低的寄存器对应内存中的低地址单元
  2. 编号高的寄存器对应内存中的高地址单元

汇编指令的执行条件

CPSR条件标志位N、Z、C、V分别表示Negative、Zero、Cary、Overflow

条件码 助记符 含义 CPSR中条件标志位
0000 eq 相等 Z = 1
0001 ne 不相等 Z = 0
0010 cs 无符号数大于/等于 C = 1
0011 cc 无符号数小于 C = 0
0100 mi 负数 N = 1
0101 pl 非负数 N = 0
0110 vs 上溢出 V = 1
0111 vc 没有上溢出 V = 0
1000 hi 无符号数大于 C = 1且Z = 0
1001 ls 无符号数小于等于 C = 0或Z = 1
1010 ge 带符号数大于等于 N = 1,V = 1或N = 0, V = 0
1011 lt 带符号数小于 N = 1,V = 0或N = 0, V = 1
1100 gt 带符号数大于 Z = 0且N = V
1101 le 带符号数小于/等于 Z = 1或 N != V
1110 al 无条件执行 -
1111 nv 从不执行 -

寄存器的使用规则

寄存器 别名 使用规则
r15 pc 程序计数器
r14 lr 连接寄存器
r13 sp 数据栈指针
r12 ip 子程序内部调用的scratch寄存器
r11 v8 ARM状态局部变量寄存器8
r10 v7、sl ARM状态局部变量寄存器7,在支持数据栈检查的ATPCS中为数据栈限制指针
r9 v6、sb ARM状态局部变量寄存器6,在支持RWPI的ATPCS中为静态基址寄存器
r8 v5 ARM状态局部变量寄存器5
r7 v4、wr ARM状态局部变量寄存器4,Thumb状态工作寄存器
r6 v3 ARM状态局部变量寄存器3
r5 v2 ARM状态局部变量寄存器2
r4 v1 ARM状态局部变量寄存器1
r3 a4 参数/结果/scratch寄存器4
r2 a3 参数/结果/scratch寄存器3
r1 a2 参数/结果/scratch寄存器2
r0 a1 参数/结果/scratch寄存器1

使用规则总结

  • 子程序间通过寄存器r0~r3来传递参数,这时可以使用它们的别名a1~a4。被调用的子程序返回前无需恢复r0~r3的内容
  • 在子程序中,使用r4~r11来保存局部变量,这时可以使用它们的别名v1~v8。如果在子程序中使用了它们的某些寄存器,子程序进入时要保存这些寄存器的值,在返回前恢复它们;对于子程序中没有使用到的寄存器,则不必进行这些操作。在Thumb程序中,通常只能使用寄存器r4~r7来保存局部变量
  • 寄存器r12用作子程序间scratch寄存器,别名为ip
  • 寄存器r13用作数据栈指针,别名为sp。在子程序中寄存器r13不能用作其它用途。它的值在进入、退出子程序时必须相等
  • 寄存器r14称为连接寄存器,别名lr。它用于保存子程序的返回地址。如果在子程序中保存了返回地址,r14可以用作其它用途
  • 寄存器r15是程序计数器,别名为pc。它不能用作其它用途

数据栈使用规则

数据栈有两个增长方向:向内存地址减小的方向增长时,称为DESCENDING栈;向内存地址增加的方向增长时,称为ASCENDING栈

所谓数据栈的增长就是移动栈指针。当栈指针指向栈顶元素(最后一个入栈的数据)时,称为Full栈;当栈指针指向栈顶元素(最后一个入栈的数据)相邻的一个空的数据单元时,称为Empty栈

综合这两个特点,数据栈可以分为以下4种:

  1. FD:Full Descending,满递减
  2. ED:Empty Descending,空递减
  3. FA:Full Ascending,满递增
  4. EA:Empty Ascending,空递增

ATPCS规定数据栈为FD类型,并且对数据栈的操作是8字节对齐的。使用stmdb/ldmia批量内存访问指令来操作FD数据栈

使用stmdb命令往数据栈中保存内容时,先递减sp指针,再保存数据;使用ldmia命令从数据栈中恢复数据时,先获取数据,再递增sp指针,sp指针总是指向栈顶元素。

猜你喜欢

转载自blog.csdn.net/o_rdwr/article/details/82182576