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

0x00 用到的书籍

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

0x01 原生程序的生成过程

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

需要编译的C语言代码

#include 

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汇编的程序结构_第1张图片

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同时用来存放函数调用的返回值。由函数调用方来平衡堆栈。

你可能感兴趣的:(安卓逆向基础)