第七章 ARM反汇编基础
android指令支持
这里只记我平时常用的两种架构
armeabi-v7a
- Thumb-2指令集扩展: 性能堪比32位ARM指令,简洁性类似于之前16位的Thumb指令集,同时支持16位与32位指令集的混合使用。
- VFP硬件FPU指令:包括VFPv3-D16,除了ARM核心中的16个32位寄存器,还包含16个专用的64位浮点寄存器。
同时支持可选扩展NEON、VFPv3-D32和ThumbEE, armeabi-v7a已经被并入AArch32架构。
arm64-v8a
兼容armabi-v7a,并支持AArch64架构,VFP扩展升级为v4版本, NEON指令集扩展是必需的。
64位arm64-v8a规格的处理器支持AArch64和AArch32两种运行模式。
在AArch64下,所有代码数据寻址采用64位地址空间,寄存器也采用64位的。
在AArch32模式为32位,因此,在此模式下代码数据寻址和寄存器的使用与之前一样,才有32位的。
因此,arm64-v8a完全兼容armeabi-v7a。
ARM原生程序的生成过程
- 编写代码
编译代码
编写完代码之后需要进行代码的编译,此处跟书本不一样,主要采用clang,此处采用官网的说明,而书中采用的是gcc
Android NDK编译从 NDK r19 开始,NDK 默认安装的工具链可供使用。与任意构建系统进行交互时不再需要使用 make_standalone_toolchain.py 脚本。为了确保使用正确的架构进行构建,请在调用 Clang 时使用 -target 传递适当的目标,或调用具有目标前缀的 Clang。例如,若要为 64 位 ARM Android 编译值为 21 的 minSdkVersion,可使用以下两种方法,您可以选择使用其中最方便的方法
$ $NDK/toolchains/llvm/prebuilt/$HOST_TAG/bin/clang++ -target aarch64-linux-android21 foo.cpp $ $NDK/toolchains/llvm/prebuilt/$HOST_TAG/bin/aarch64-linux-android21-clang++ foo.cpp
如上图,执行完这一句之后sum.cpp已经被编译完成。
完成代码的预处理
预处理阶段,编译器将代码中的预处理指令进行处理。例如#include 中包含的头文件会全部编译进来,#define预定义、#if预条件处理等也都会在这里被编译器处理。详细的输出信息通过-E进行查看。
clang++ -E -fPIE file.cpp -o file.i
相应的.i文件的内容如下,由于我包含了一个iostream,结果几行代码,预编译之后变成了将近30000行。
编译
该阶段会进行语法等代码规范性检查,检查无误会把代码翻译成ARM汇编代码,输出信息通过-s选项进行查看。clang++ file.i -S -fPIE -o file.s
执行该命令后会生成file.s的汇编文件。汇编
汇编阶段主要用来将汇编文件生成目标文件。clang++ -c file.s -o file.o
- 链接
将所有的目标合并,生成最终的可执行程序或动态链接库。clang++ file.o -fPIE -o file
Arm汇编基本语法
.text
在编译后用于存放代码的代码段。位于ARM EABI的ELF中。
.rodata
用于存放数据的数据段。位于ARM EABI的ELF中。
.section
汇编代码中用于声明段时需要使用的伪指令。.text实际上写作.section.text,但其比较特殊可简写。使用.section声明的所有的段信息在编译后可通过执行命令来查看。
.global
用于声明全局符号。可以被外部程序引用。