一个ARM原生程序 Hello

main函数的代码,内容如下:

#include <stdio.h>

int main(int argc, char* argv[]){
	printf("Hello\n");
	return 0;
}
其原生程序代码如下:

1   EXPORT main
2   main
3   var_C= -0xC
4   var_8= -8
5   STMFD SP!, {r11, LR}
6   ADD   R11, SP, #4
7   SUB   SP, SP, #8
8   STR   R0, [R11,#var_8]
9   STR   R1, [R11,#var_c]
10   LDR   R3, =(aHelloArm - 0x8300)
11   ADD   R3, PC, R3         ; "Hello"
12   MOV   R0, R3             ; s
13   BL    puts
14   MOV   R3, #0
15   MOV   R0, R3
16   STB   SP, R11, #4
17   LDMFD SP!, {R11, PC}

定义:

由一条条ARM汇编指令所组成的汇编代码,我们将其称为原生程序的反汇编代码。

逆向原生程序就是通过阅读这些汇编代码来了解原生程序的功能及流程。

第1行的"EXPORT main"表明这个main函数式被程序导出的。

第2行的main为函数的名称。(JDA Pro能自动识别原生程序中所有的函数及其名称。)

第3行是IDA Pro识别出的栈变量。IDA Pro是通过函数中分配的栈空间来识别栈变量的。

本实例是依据第7行的"SUB SP,SP,#8"指令来完成的,

其中SUB为指令操作码,表示减法操作,SP为堆栈指令寄存器,

这条指令的含义是将SP寄存器的值减去8后重新赋给SP寄存器,

作用是在退栈上分配8个字节的空间,也就是栈变量var_C与var_8的空间。

第5-17行是main函数指令部分。整段代码涉及到8条指令,下面简单地介绍一下它们的功能。

第5行的STMFD与17行的LDMFD是堆栈寻址指令,

STMFD指令用于把寄存器的值压入堆栈,

在本实例中是为了保护原始寄存器的值(因为这些寄存器在下面可能会被使用,它们的值在使用前需要保存下来,在程序返回的时候恢复)。

LDMFD指令用于从堆栈中恢复寄存器的值,作用于STMFD恰恰相反。

第6行的ADD与第16行的SUB是算术指令。

ADD为加法指令,"ADD R11,SP,#4"就是将SP寄存器的值加4后赋给R11寄存器。

SUB为减法指令,第16行的代码功能与第6行恰恰相反。

第8-9行的STR与第10行的LDR是存储器访问指令。

存储器指的就是内存地址,通常也可以称为内存单元或存储单元,

存储器的访问包含从存储器中读取与写入数据到存储器中,

ARM指令中将存储器使用一对中括号"[]"表示,

STR是写存储器指令,

例如第8行"STR R0,[R11,#var_8]"就是将R0寄存器的值保存到栈变量var_8中,

第9行的"STR R1,[R11,#var_C]"则将R1寄存器的值保存到栈变量var_C中。

第12行的MOV为数据处理指令。

它用于寄存器间的数据传送,如"MOV R0,R3"表示把R3寄存器的值赋给R0寄存器。

第13行的BL为带链接的跳转指令。

完成类似其它编程语言中子程序调用的功能,如"BL puts"就是调用puts函数。

puts为标准输入输出函数中printf的实现,其作用是向标准输出设备输出指定的内容,本实例中输出的内容为"Hello"字符串。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值