ARM 可执行程序的生成过程

打印 上一主题 下一主题

主题 882|帖子 882|积分 2646

一:ARM 可执行程序的生成过程

1. 课程内容介绍



  • 汇编语言:汇编语言是与盘算机硬件直接交互的低级语言,使用助记符表示呆板指令。学习汇编语言有助于明白盘算机的工作原理和优化程序性能。
  • 调试程序:调试是软件开辟中不可或缺的一部门,调试程序帮助开辟者识别和修复代码中的错误。把握调试工具(如 GDB)是提高开辟效率的关键。
  • C 和 C++ 逆向工程:逆向工程是分析和明白已有程序的过程,通常用于安全分析、毛病挖掘和软件兼容性研究。学习 C 和 C++ 的逆向工程有助于明白程序的结构和逻辑。
2. ARM 汇编与指令集



  • ARM 指令集:ARM 是一种广泛使用的 RISC(精简指令集盘算)架构,具有高效的指令集和低功耗特性。学习 ARM 指令集有助于编写高效的嵌入式系统和移动应用程序。
  • ARM 可执行程序的生成过程:相识 ARM 可执行程序的生成过程,包括编写源代码、编译、链接等步骤,是把握 ARM 开辟的底子。
ARM 可执行程序的生成步骤

1. 通过例子学习生成过程



  • 通过一个简单的示例(如 Hello World 程序),逐步演示 ARM 可执行程序的生成过程,帮助门生明白每个步骤的作用。
2. 步骤包括编写源代码、编译、链接等



  • 编写源代码:使用 C 或 C++ 编写源代码,定义程序的功能。
  • 编译:将源代码转换为呆板代码,生成中央文件。
  • 链接:将多个中央文件和库文件链接成终极的可执行文件。
编写 Hello World 程序

1. 编写最简单的 Hello World 程序



  • 示例代码:
    1. #include <stdio.h>
    2. int main() {
    3.     printf("Hello, World!\\n");
    4.     return 0;
    5. }
    复制代码
2. 使用 clang 编译器举行编译



  • 使用 clang 编译器生成 64 位可执行文件:
    1. clang -o hello hello.c
    复制代码
编译 32 位 ARM 可执行程序

1. 修改编译器目标架构



  • 使用 target 选项指定目标架构为 32 位 ARM:
    1. clang -target armv7-none-linux-gnueabi -o hello32 hello.c
    复制代码
2. 设置情况变量和使用 NDK 中的 clang



  • 介绍如何设置 Android NDK 情况,确保可以使用 NDK 中的 clang 编译器。
生成过程详细步骤

1. 预编译



  • 生成 .i 文件,展开宏和头文件,便于后续编译。
2. 编译



  • 将预编译文件编译成汇编文件 .s,生成可读的汇编代码。
3. 汇编



  • 将汇编文件汇编成中央文件 .o,这是呆板代码的中央表示。
4. 链接



  • 将多个 .o 文件链接成终极的可执行程序,生成可执行文件。
二.ARM 汇编语言结构

1. 汇编语言的结构



  • 介绍 ARM 汇编语言的基本结构,包括:

    • 处理器指定:指定使用的 ARM 处理器类型。
    • 段定义:定义代码段和数据段。
    • 符号表:用于管理变量和函数的地址。

汇编语言的结构是明白汇编程序编写和执行的底子。以下是汇编语言的一些基本组成部门和结构要素:
1. 源代码文件

汇编语言的源代码通常以 .asm 或 .s 为文件扩展名。文件中包含了汇编指令、数据定义和注释。
2. 段定义

汇编程序通常分为几个段,每个段用于差别的目标。常见的段包括:


  • 代码段(.text

    :存放程序的可执行指令。
  • 数据段(.data):存放已初始化的全局变量和静态变量。
  • BSS 段(.bss):存放未初始化的全局变量和静态变量。
  • 堆栈段(.stack):用于存放函数调用时的局部变量和返回地址。
示例:
  1. .section .text
  2. .global _start
  3. _start:
  4.     ; 程序入口
复制代码
3. 指令

指令是汇编语言的核心部门,指示 CPU 执行特定操纵。指令通常由操纵码(opcode)和操纵数(operand)组成。


  • 操纵码:指示要执行的操纵类型(如加法、减法、数据传送等)。
  • 操纵数:指示操纵的对象,可以是寄存器、内存地址或立刻数。
示例:
  1. MOV R0, #5      ; 将立即数 5 移动到寄存器 R0
  2. ADD R1, R0, #3  ; 将 R0 和立即数 3 相加,结果存入 R1
复制代码
4. 标签

标签是程序中的标识符,用于标记特定位置,通常用于控制流(如跳转和循环)。标签后面跟一个冒号。
示例:
  1. loop_start:
  2.     ; 循环体
  3.     B loop_start  ; 跳转到 loop_start 标签
复制代码
5. 注释

注释用于表明代码,帮助程序员明白程序的逻辑。注释通常以 ; 开头,后面的内容将被汇编器忽略。
示例:
  1. MOV R0, #5      ; 将 5 移动到 R0 寄存器
复制代码
6. 伪指令

伪指令是汇编语言中的指令,固然不直接对应于呆板指令,但用于控制汇编过程或定义数据。常见的伪指令包括:


  • .data:定义数据段。
  • .text

    :定义代码段。
  • .global:声明全局符号。
  • .equ:定义常量。
示例:
  1. .data
  2. myVar: .word 10  ; 定义一个名为 myVar 的变量,初始值为 10
复制代码
7. 符号表

符号表用于存储程序中使用的变量、函数和标签的名称及其地址。汇编器在汇编过程中使用符号表来剖析标签和变量的地址。
8. 汇编指令的格式

汇编指令的格式通常为:
  1. [标签] 指令 [操作数]
复制代码
其中,标签和操纵数是可选的。
示例汇编程序

以下是一个简单的汇编程序示例,展示了上述结构的应用:
  1. .section .data
  2. msg:    .asciz "Hello, World!\\n"  ; 定义字符串
  3. .section .text
  4. .global _start
  5. _start:
  6.     ; 写入字符串到标准输出
  7.     MOV R0, #1                  ; 文件描述符 1 (stdout)
  8.     LDR R1, =msg                ; 加载字符串地址
  9.     MOV R2, #14                 ; 字符串长度
  10.     SWI 0x9000004               ; 系统调用:write
  11.     ; 退出程序
  12.     MOV R0, #0                  ; 退出状态
  13.     SWI 0x9000001               ; 系统调用:exit
复制代码
2.语法、指令和伪指令

讲授汇编语言中的基本语法规则、常用指令和伪指令的使用。
1. 基本语法规则

汇编语言的语法规则通常包括以下几个方面:
1.1 指令格式

汇编指令的基本格式为:
  1. [标签] 指令 [操作数]
复制代码


  • 标签(可选):用于标识指令的位置,通常以冒号结尾。
  • 指令:表示要执行的操纵。
  • 操纵数(可选):指令的操纵对象,可以是寄存器、内存地址或立刻数。
1.2 大小写

汇编语言通常不区分大小写,但为了可读性,指令和伪指令通常使用大写字母,而标签和变量名使用小写字母。
1.3 注释

注释以 ; 开头,后面的内容将被汇编器忽略。注释用于表明代码,帮助程序员明白程序逻辑。
示例:
  1. MOV R0, #5      ; 将 5 移动到 R0 寄存器
复制代码
1.4 空格和缩进

指令和操纵数之间用空格或制表符分隔。标签和指令之间可以使用空格或制表符举行缩进,以提高可读性。
3. 常用指令

汇编语言中的指令通常分为几类,以下是一些常用的指令及其功能:
3.1 数据传送指令



  • MOV:将数据从一个位置移动到另一个位置。
    1. MOV R0, R1      ; 将 R1 的值移动到 R0
    2. MOV R2, #10     ; 将立即数 10 移动到 R2
    复制代码
3.2 算术运算指令



  • ADD:执行加法运算。
    1. ADD R0, R1, R2  ; 将 R1 和 R2 相加,结果存入 R0
    复制代码
  • SUB:执行减法运算。
    1. SUB R0, R1, R2  ; 将 R1 减去 R2,结果存入 R0
    复制代码
3.3 逻辑运算指令



  • AND:执行按位与运算。
    1. AND R0, R1, R2  ; R1 和 R2 按位与,结果存入 R0
    复制代码
  • ORR:执行按位或运算。
    1. ORR R0, R1, R2  ; R1 和 R2 按位或,结果存入 R0
    复制代码
3.4 控制流指令



  • B:无条件跳转。
    1. B label         ; 跳转到指定标签
    复制代码
  • BL:分支并链接,用于调用函数。
    1. BL function      ; 调用 function 函数
    复制代码
  • CMP:比较两个寄存器的值。
    1. CMP R0, R1      ; 比较 R0 和 R1
    复制代码
3.5 条件跳转指令



  • BEQ:假如相称则跳转。
    1. BEQ label       ; 如果上一次比较结果相等,则跳转到 label
    复制代码
  • BNE:假如不相称则跳转。
    1. BNE label       ; 如果上一次比较结果不相等,则跳转到 label
    复制代码
4. 伪指令

伪指令是汇编语言中的指令,固然不直接对应于呆板指令,但用于控制汇编过程或定义数据。常见的伪指令包括:
4.1 段定义伪指令



  • .data:定义数据段,存放已初始化的变量。
    1. .data
    2. myVar: .word 10  ; 定义一个名为 myVar 的变量,初始值为 10
    复制代码
  • .text

    :定义代码段,存放可执行指令。
    1. .text
    复制代码
4.2 全局符号伪指令



  • .global:声明全局符号,使其在其他文件中可见。
    1. .global _start   ; 声明 _start 为全局符号
    复制代码
4.3 常量定义伪指令



  • .equ:定义常量。
    1. PI: .equ 3.14    ; 定义常量 PI
    复制代码
4.4 字节和字定义伪指令



  • .byte:定义一个字节。
    1. myByte: .byte 0xFF  ; 定义一个字节,值为 255
    复制代码
  • .word:定义一个字(通常为 4 字节)。
    1. myWord: .word 0x12345678  ; 定义一个字,值为 0x12345678
    复制代码
三:ARM 寄存器介绍

1. ARM32 位架构中的寄存器



  • 介绍 ARM32 位架构中的寄存器类型:

    • 通用寄存器:用于存储数据和地址。
    • 分组寄存器:用于特定功能,如程序计数器(PC)和堆栈指针(SP)。
    • 特殊寄存器:用于控制和状态信息。

2. 各寄存器的用途和含义

在 ARM 架构中,寄存器是 CPU 内部用于存储数据和地址的高速存储单位。ARM 处理器通常有多种类型的寄存器,每种寄存器都有特定的功能和用途。以下是 ARM 架构中各类寄存器的详细表明:
1. 通用寄存器(R0 - R15)

ARM 处理器通常有 16 个通用寄存器,编号从 R0 到 R15。它们的重要功能如下:


  • R0 - R12:这些寄存器是通用寄存器,可以用于存储数据、地址或暂时变量。程序员可以自由使用这些寄存器举行盘算和数据传输。
  • R13(SP):堆栈指针寄存器(Stack Pointer)。它指向当前堆栈的顶部,堆栈用于存储函数调用时的局部变量和返回地址。堆栈的操纵通常涉及到 PUSH 和 POP 指令。
  • R14(LR):链接寄存器(Link Register)。在调用函数时,返回地址会被存储在 LR 中。当函数执行完毕后,可以通过 BX LR 指令返回到调用函数的位置。
  • R15(PC):程序计数器(Program Counter)。它指向当前正在执行的指令的地址。每当执行一条指令时,PC 会自动增加,以指向下一条指令。PC 也可以被直接修改,以实现跳转和分支。
2. 特殊寄存器

除了通用寄存器,ARM 还包含一些特殊寄存器,用于特定的功能:


  • CPSR(Current Program Status Register):当出息序状态寄存器。它包含了当前处理器的状态信息,包括条件标记(如零标记、负标记、溢出标记和进位标记)、中断使能位和当前处理器模式(如用户模式、特权模式等)。CPSR 的状态会影响条件执行指令的举动。
  • SPSR(Saved Program Status Register):保存程序状态寄存器。它用于在处理异常或中断时保存 CPSR 的状态,以便在处理完后规复。SPSR 重要在异常处理程序中使用。
3. 浮点寄存器(VFP 寄存器)

在支持浮点运算的 ARM 处理器中,通常有一组浮点寄存器(V0 - V31),用于存储浮点数和举行浮点运算。这些寄存器的使用场景包括:


  • 浮点盘算:执行浮点加法、减法、乘法和除法等运算。
  • SIMD 操纵:在某些 ARM 处理器中,浮点寄存器还可以用于单指令多数据(SIMD)操纵,以提高数据处理效率。
4. SIMD 寄存器(NEON 寄存器)

在支持 NEON 技能的 ARM 处理器中,通常有一组 SIMD 寄存器(Q0 - Q31),用于并行处理多个数据元素。这些寄存器的使用场景包括:


  • 图像处理:在图像处理应用中,NEON 寄存器可以用于并行处理像素数据。
  • 音频处理:在音频信号处理应用中,NEON 寄存器可以用于并行处理音频样本。
5. 寄存器的使用场景



  • 函数参数传递:在 ARM 架构中,通常使用 R0 - R3 寄存器传递前四个函数参数,超出部门则通过堆栈传递。
  • 返回值:函数的返回值通常存储在 R0 中。
  • 暂时存储:在执行复杂盘算时,可以使用 R4 - R12 作为暂时存储寄存器。
  • 异常处理:在处理异常时,CPSR 和 SPSR 寄存器用于保存和规复处理器状态。
总结

ARM 架构中的寄存器分为通用寄存器和特殊寄存器,每种寄存器都有特定的功能和使用场景。明白各寄存器的用途和含义对于编写高效的汇编程序和优化代码性能至关重要。通过合理使用寄存器,程序员可以提高程序的执行效率,淘汰内存访问的开销。
四:汇编指令详解

1. 常用指令



  • 详细表明汇编语言中的常用指令,如:

    • PUSH:将数据压入堆栈。
    • MOVE:数据传送指令。
    • STR:将寄存器中的数据存储到内存。
    • LDR:从内存加载数据到寄存器。
    • ADD:加法运算指令。
    • BL:分支并链接,用于调用函数。

2. 实例说明指令的作用和用法

参考我之前发的文章。

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

惊雷无声

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表