ARM汇编语言学习笔记(一)---ARM汇编的程序结构

时间:2023-01-19 03:33:14

0x00 用到的书籍

《Android软件安全与逆向分析》第六章

0x01 原生程序的生成过程

笔者是在Linux环境下测试的,详细过程见书中说明

需要编译的C语言代码

#include <stdio.h>

int main(int argc, char* argv[]){
printf("Hello ARM!\n");
return 0;
}
  • 预处理,生成hello.i文件
 gcc -E hello.c -o hello.i
  • 编译
 gcc -S hello.i -o hello.s
  • 汇编,生成二进制目标文件
 gcc -c hello.s -o hello.o
  • 链接,生成hello可执行文件
 gcc hello.o -o hello

ARM汇编语言学习笔记(一)---ARM汇编的程序结构

0x02 完整ARM汇编结构

下面打开生成的.文件

    .arch armv5te            @处理器架构
.fpu softvfp @浮点协处理器类型
.eabi_attribute 20, 1 @接口属性
.eabi_attribute 21, 1
.eabi_attribute 23, 3
.eabi_attribute 24, 1
.eabi_attribute 25, 1
.eabi_attribute 26, 2
.eabi_attribute 30, 6
.eabi_attribute 18, 4
.file "hello.c" @源文件名
.section .rodata @声明只读数据
.align 2 @声明对齐方式2^2=4字节
.LC0: @标号LC0
.ascii "Hello ARM!\000"@声明字符串
.text @声明代码段
.align 2 @声明对齐方式4字节
.global main @全局符号main
.type main, %function @main类型为函数
main: @标号main
@ args = 0, pretend = 0, frame = 8
@ frame_needed = 1, uses_anonymous_args = 0
stmfd sp!, {fp, lr} @将fp,lr压入堆栈
add fp, sp, #4 @初始化fp寄存器,设置栈帧,用于访问局部变量
sub sp, sp, #8 @开辟栈空间
str r0, [fp, #-8] @保存第一个参数
str r1, [fp, #-12] @保存第二个参数
ldr r3, .L3 @取标号.L3处的内容,
.LPIC0:
add r3, pc, r3
mov r0, r3
bl puts(PLT)
mov r3, #0
mov r0, r3
sub sp, fp, #4
ldmfd sp!, {fp, pc}
.L4:
.align 2
.L3:
.word .LC0-(.LPIC0+8)
.size main, .-main
.ident "GCC: (GNU) 4.4.3"
.section .note.GNU-stack,"",%progbits

0x03 处理器架构定义

.arch armv5te            @处理器架构
.fpu softvfp @浮点协处理器类型
.eabi_attribute 20, 1 @接口属性
.eabi_attribute 21, 1
.eabi_attribute 23, 3
.eabi_attribute 24, 1
.eabi_attribute 25, 1
.eabi_attribute 26, 2
.eabi_attribute 30, 6
.eabi_attribute 18, 4

0x04 段定义

本例子中定义了三个段
如下:

.section    .rodata                           @声明只读数据
.text @定义了代码段
..section .note.GNU-stack,"",%progbits @保护代码,禁止生成可执行堆栈。

0x05 注释与标号

  • 单行注释用@表示,例如
@声明只读数据
  • 多行注释用/* */

0x06 汇编器指令

程序中所有以点开头的都是汇编器指令,就是给汇编器读的指令,不属于ARM指令集

.flie:指定了源文件名。手写可忽略
.align:指定了代码对齐方式你后面跟的是2的次方
.ascii:声明字符串
.global:声明全局符号。全局符号是指在本程序外可访问的符号。
.type:指定符号的类型,“.type main,%function”表示main为函数
.word: 用来存放地址。
.size:设定指定符号的大小。“.size main,.-main”中的”.”表示当前地址,减去main符号的地址为整个main函数的大小。
.ident:编译器标识,无实际意义。

0x07 子程序与参数传递

  • 函数声明方法
.global 函数名
.type 函数名,“%function
函数名:

<函数体>
  • 实例
.global MyAdd
.type MyAdd,%function
MyAdd:
ADD r0,r0,r1 @两个数相加
MOV pc,lr @ 函数返回
  • ARM参数传递规定(重要)
    R0-R3这4个寄存器用来传递函数调用的第1到4个参数,超出的通过堆栈来传递,R0同时用来存放函数调用的返回值。由函数调用方来平衡堆栈。