前言

一个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指针总是指向栈顶元素。