从最简单的实例学习ARM 指令集(一)

打算为入门ARM指令集写点初级文章,没什么远大理想,纯当娱乐算了。

首先编辑一个最简单的函数:

#include <stdio.h>

void main()
{
  int d = 4;
}

然后编译:arm-linux-gnueabihf-gcc test.c -o test1

然后看看汇编代码:arm-linux-gnueabihf-objdump -D test1;每一句的含义我已经给出详细注释

0000835c <main>:

835c:       b480            push    {r7}           
;程序用到了r7寄存器,所以需要保护以免破坏之前的数据

835e:       b083            sub     sp, #12     
;堆栈向下增长栈用的不多,只需要12个字节就够用了: int d需要4个,main的参数需要8个

8360:       af00            add     r7, sp, #0  
;因为堆栈寄存器sp不能用作寄存器寻址,所以没办法,只好用r7 = sp + 0这种笨办法

8362:       f04f 0304       mov.w   r3, #4   
;参与int d = 4这条语句的是r3,这是通用寄存器,spec定义大家都可以用,不需要保护

8366:       607b            str     r3, [r7, #4]   
; 把4存储到sp+4所指定的栈里,c语言描述:*(sp + 4) = 4

8368:       f107 070c       add.w   r7, r7, #12 
;还记得第二条:sub sp, #12吗?此句和下一句是为从堆栈里恢复原来的r7--pop {r7},做准备;

836c:       46bd            mov     sp, r7         ;r7已经是原来的sp了

836e:       bc80            pop     {r7}              ;弹出sp指向的内存数据给r7,c语言:r7 = *sp;

8370:       4770            bx      lr                   ; 跳转到lr地址--进入main函数的下一条地址

8372:       bf00            nop

我们再编辑一个稍微复杂一点点函数:

#include <stdio.h>

void main()
{
  int a = 1;
  char b = 2;
  short c = 3;
  int d = 4;
  int e;
  e = b;
  printf("%d\n", e);
  e = a;
  printf("%d\n", e);
  e = c;
  printf("%d\n", e);
  e = d;
  printf("%d\n", e);
}

然后看看汇编代码:

00008394 <main>:
    8394:       b580            push    {r7, lr}
    8396:       b084            sub     sp, #16
    8398:       af00            add     r7, sp, #0
    839a:       f04f 0301       mov.w   r3, #1
    839e:       603b            str     r3, [r7, #0]
    83a0:       f04f 0302       mov.w   r3, #2
    83a4:       73fb            strb    r3, [r7, #15]
    83a6:       f04f 0303       mov.w   r3, #3
    83aa:       81bb            strh    r3, [r7, #12]
    83ac:       f04f 0304       mov.w   r3, #4
    83b0:       607b            str     r3, [r7, #4]
    83b2:       7bfb            ldrb    r3, [r7, #15]
    83b4:       60bb            str     r3, [r7, #8]
    83b6:       f248 4360       movw    r3, #33888      ; 0x8460
    83ba:       f2c0 0300       movt    r3, #0
    83be:       4618            mov     r0, r3
    83c0:       68b9            ldr     r1, [r7, #8]
    83c2:       f7ff ef92       blx     82e8 <_init+0x20>
    83c6:       683b            ldr     r3, [r7, #0]
    83c8:       60bb            str     r3, [r7, #8]
    83ca:       f248 4360       movw    r3, #33888      ; 0x8460
    83ce:       f2c0 0300       movt    r3, #0
    83d2:       4618            mov     r0, r3
    83d4:       68b9            ldr     r1, [r7, #8]
    83d6:       f7ff ef88       blx     82e8 <_init+0x20>
    83da:       f9b7 300c       ldrsh.w r3, [r7, #12]
    83de:       60bb            str     r3, [r7, #8]
    83e0:       f248 4360       movw    r3, #33888      ; 0x8460
    83e4:       f2c0 0300       movt    r3, #0
    83e8:       4618            mov     r0, r3
    83ea:       68b9            ldr     r1, [r7, #8]
    83ec:       f7ff ef7c       blx     82e8 <_init+0x20>
    83f0:       687b            ldr     r3, [r7, #4]
    83f2:       60bb            str     r3, [r7, #8]
    83f4:       f248 4360       movw    r3, #33888      ; 0x8460
    83f8:       f2c0 0300       movt    r3, #0
    83fc:       4618            mov     r0, r3
    83fe:       68b9            ldr     r1, [r7, #8]
    8400:       f7ff ef72       blx     82e8 <_init+0x20>
    8404:       f107 0710       add.w   r7, r7, #16
    8408:       46bd            mov     sp, r7
    840a:       bd80            pop     {r7, pc}
时间: 2024-10-28 12:15:58

从最简单的实例学习ARM 指令集(一)的相关文章

Android上学习ARM指令集之开篇

工作中经常碰到crash的问题,如果是Debug版本,有源代码,那还好,调试信息多.万一Release给QA甚至客户之后,再发现crash之类的问题,如果不熟悉ARM指令.看不懂现场,那调试起来可就费劲了.往往只能到处去猜,相信大家都有过这种难过的经历. 这段时间比较闲,正好利用起来为入门ARM指令集写点初级文章,没什么远大理想,写到哪里算哪里,权当娱乐罢了. 环境准备:现在的学习环境可真是方便啊,几乎人手一台android手机,而绝大多数手机都是ARM家族的,所以只需要给手机或者平板电脑安装一

ARM指令集学习总结-转载

ARM指令集比较简单,本文介绍ARM指令集中需要注意和不易理解的地方. 一.ARM指令集是32位的,程序的启动都是从ARM指令集开始,包括所有异常中断都是自动转化为ARM状态,并且所有的指令都可以是有条件执行的.         二.ARM指令集是Load/Store型的,只能通过Load/Store指令实现对系统存储器的访问,而其他的指令都是基于处理器内部的寄存器操作完成的,这和INTEL汇编是不同的,初学者很不易理解.        三.指令的后缀:     "S"  可选后缀,若

【转】ARM指令集

ARM指令集 6种类型(53种主要助记符) : 数据处理指令(22种主要助记符) 跳转指令(4种主要助记符) Load/Store指令(16种主要助记符) 程序状态寄存器指令(2种主要助记符) 协处理器指令(5种主要助记符) 软件中断指令 (2种主要助记符) 数据处理指令 数据处理指令大致可分为3类: 数据传送指令: 算术逻辑运算指令: 乘法指令 比较指令. 数据处理指令只能对寄存器的内容进行操作,而不能对内存中的数据进行操作.所有ARM数据处理指令均可选择使用S后缀,并影响状态标志. 数据处理

[ARM] ARM指令集

ARM指令集 一.ARM指令的格式和分类 经典ARM指令格式如下: <opcode> {<cond>} {S} <Rd>,<Rn>,<operand2> <opcode>   {<cond>}   {S}    <Rd>,<Rn>,<operand2> <> 为必选项,{}为可选项 为操作码,如ADD表示算术加操作指令 {} 决定指令执行条件域 {S} 决定指令执行是否影响C

ARM指令集、Thumb指令集、Thumb-2指令集

MCU使用什么指令集主要由内核决定的,比如Cortex-M3使用的是Thumb-2指令集 ARM指令集: 编代码全部是 32bits 的,每条指令能承载更多的信息,因此使用最少的指令完成功能, 所以在相同频率下运行速度也是最快的, 但也因为每条指令是32bits 的而占用了最多的程序空间. Thumb指令集: 编代码全部是 16bits 的,每条指令所能承载的信息少,因此它需要使用更多的指令才能完成功能, 因此运行速度慢, 但它也占用了最少的程序空间 Thumb-2指令集:在前面两者之间取了一个

Thumb指令集与ARM指令集的差别

Thumb指令集 Thumb指令能够看做是ARM指令压缩形式的子集.是针对代码密度[1]的问题而提出的.它具有16为的代码密度.Thumb不是一个完整的体系结构,不能指望处理程序仅仅运行Thumb指令而不支持ARM指令集. 因此.Thumb指令仅仅须要支持通用功能.必要时,可借助完好的ARM指令集,比如:全部异常自己主动进入ARM状态. 在编写Thumb指令时.先要使用伪指令CODE16声明,并且在ARM指令中要使用BX指令跳转到Thumb指令,以切换处理器状态.编写ARM指令时,可使用伪指令C

ARM指令集——跳转指令

ARM 汇编指令条件执行 在ARM模式下,任何一条数据处理指令可以选择是否根据操作的结果来更新CPSR寄存器中的ALU状态标志位.在数据处理指令中使用S后缀来实现该功能. 不要在CMP,CMN,TST或者TEQ指令中使用S后缀.这些比较指令总是会更新标志位. 在Thumb模式下,所有数据处理指令都更新CPSR中的标志位.有一个例外就是:当一个或更多个高寄存器被用在MOV和ADD指令时,此时MOV和ADD不能更新状态标志. 几乎所有的ARM指令都可以根据CPSR中的ALU状态标志位来条件执行.参见

ARM指令集----杂项指令

ARM指令集可以分为6类,即是跳转指令,数据处理指令,程序状态传输指令,Load.Store指令,协处理器指令和异常中断指令 跳转指令: 在ARM中有两种方式可以实现程序的跳转,一种是跳转指令,另一种是直接向PC寄存器写入目标地址的值 通过直接向PC寄存器写入目标寄存器的数字可以实现在4GB 地址空间的任意跳转,这种跳转又称为长跳转,如果在残肢令前面使用MOV LR,PC等指令,可以保存返回来的地址值,这样就实现了在4GB空间中的子程序调用 ARM的跳转指令可以从当前指令向前或者是向后的32位的

ARM指令集应该也算得上是iOS逆向工程的基础

当然,如果读者仅仅是想阅读污点跟踪相关的代码,可以去github中按照自己的需要下载对应部分源码即可.如实现变量级.Native级污点跟踪的代码基本都在dalvik目录下,单个函数调用操作所使用的栈部分被称为栈帧(stack frame)结构,其一般结构如上图所示.栈帧结构的两端由两个指针来指定.寄存器ebp通常用做帧指针(frame pointer),而esp则用作栈指针(stack pointer).在函数执行过程中,栈指针esp会随着数据的入栈和出栈而移动,因此函数中对大部分数据的访问都基