6.1原生程序ARM汇编言语,逆向你的helloworld
6.2原生程序的生成进程
1:预处理
“如include头文件”包含的头文件悉数编译进来,还有#define预界说,#if预条件处理等也都在这儿被编译器处,具体的输出能够给gcc编译器传递”-E“,选项检查。
2,编译
编译器首先要检查代码的规范性,以及是有语法错误等,以及代码实践要做的作业,检查无误后,gcc编译器把代码翻译成ARM汇编言语代码,能够为gcc编译器传递”-S“选项检查输出,履行”gcc-s hello.i“ -o hello.s 后生成hello.s汇编文件。
3,汇编
这个阶段会调用衔接器将汇编成二进制文件的方针文件,以上一末节的hello为例,履行”gcc-c hello.s -o hello.o“ 后生成hello.o方针文件。
4,衔接
这个阶段编译器会调用衔接器将二进制的方针文件衔接成Android渠道可履行的ARM原生程序,以上一个末节为hello为例,履行gcc hello.o -o hello 后会生成hello可履行文件。
6.2.3有必要要了解的ARM常识
总结:
1:c言语编写代码在编译时有一个进程,是将其转换成ARM汇编代码,所以能够这么了解,c言语完结的功用ARM
汇编言语都能完结。
2,ARM汇编言语中特有的寄存器。寄存器是处理特有的高速存储部件,它们能够用来暂存指令,数据和位址,高档言语用到中用到的变量,常量,结构体,类等数据用到了ARM汇编言语中,便是运用寄存器保存的值或内存地址,寄存器的数据量有限,ARM微处理器共有37个32位寄存器,其间31个为通用寄存器,6个为状况寄存器,ARM处理器器支撑7中运转方法。
1;用户方法(usr)ARM 处理器正常的程序履行状况。
2;快速中止方法(fiq):用与高速数据传输或通道处理
3;外部中止方法(irp)用于通用的中止处理。
4;管理方法(svc)操作系统运用的保护方法
5;数据拜访停止方法(abt);当数据或指令预取停止进入该方法,可用于虚拟存储及存储数据。
6;系统方法(sys):运转具有特权的操作系统使命。
7;未界说指令停止方法(und):当未界说的指令履行时进入该方法。
Thumb是ARM系统结构中一种16位的指令集。
从ARMv4T之后的ARM处理器有一种16-bit指令方法,叫做Thumb,或许跟每个条件式履行指令均耗用4位元的景象有关。Thumb指令集能够看作是ARM指令紧缩方法的子集,它是为减小代码量而提出,具有16bit的代码密度。Thumb指令系统并不完好,只支撑通用功用,必要时仍需求运用ARM指令,如进入反常时。其指令的格局与运用方法与ARM指令集相似,并且运用并不频频,Thumb指令集作一般了解
ARM汇编言语程序结构
1.一个完好的ARM汇编指令包含处理器架构界说,数据段,代码与main函数。
2.段界说.data的数据段中,
假如细分的话,
.rodata的只读数据段中,这些数据段不能够履行的。
.text的代码段中ARM汇编运用,
“.section”指令来界说段
.section name
3.注释与标号
/*…*/
4.汇编器指令
程序中所有以“.”最初的指令都是汇编指令,
.file:指定了源文件名,实例hello.s是从hello.c编译得来的,手写汇编代码能够疏忽。
.align:指定了代码的对齐方法,后边跟的数值为2的次方,如:“.align4” 表明2^4=16个字节对齐
.ascii:声明大局符号。大局符号是指在本程序外能够拜访的符号。
.global:声明大局符号。大局符号是指在本程序外能够拜访的符号。
.type:指定符号的类型。“.type main,%function ” 表明main符号为函数。
.word:用来存储地址址。”word. LCD-(LPIC0+8)”寄存的是一个与地址无关的偏移量,
.size:设置指定符号的巨细。“.size main ,-.main”中的点,“.表明当时地址”,减去main符号的地址即为整个
main符号的地址即为整个main函数的巨细。
5.子线程与参数传递
.global 函数名
.type 函数名 ,%function 函数名
函数名
<....函数体...>
例如声明一个完结两个数相加的函数的代码为:
.global MyAdd
.type MyAdd,%function
MyAdd:
ADD:r0, r0,r1 @ 两个数相加
mov pc,lr@函数回来
ARM汇编中规则,R0-R3这4个寄存器用来传递函数调用的第1到第4个参数,超出的参数经过仓库来传递。R0一起用来寄存函数调用的回来值,被调用的函数在回来前无需这些寄存器的内容。
6.4寄存器
1,当即寻址
MOV R0 ,#1234 指令履行后,R0=1234,当即数“#作为前缀”,表明十六进制数值时以”0x“最初
2,寄存器寻址
MOV R0 ,R1 寄存器寻址中,操作数的值在寄存器,指令履行时直接从寄存器中取值进行操作
3,寄存器移位寻址
LSL :逻辑左移->移位后寄存器空出的低位补0
LSR:逻辑右移->移位后寄存器空出的高位补0
例如:
MOVR0 ,R1,LSL #2 表明:指令的功用是将R1寄存器左移2位,即“R1<<2” 后赋值给R0寄存器,指令履行后R0=R1*4;
4,寄存器直接寻址
例如:寄存器直接寻址码给出寄存器是操作数的地址指针,所需的操作数保存在寄存器指定地址的存储单元
中,
例如:
LDRR0 ,[R1]
指令功用是将R1寄存器的数值作为地址,取出地址中的值赋值给R0寄存器。
5,基址寻址
基址寻址是将地址码给出的寄存器与偏移量相加,构成操作数的有用地址,所需的操作数保存在有用地址所指向的存储单元中,基址寻址多用于查表,数组拜访等操作,
例如:LDRR0 ,[R1,#-4]
指令的功用是 将R1寄存器的数值减4作为地址,取出此地址的值赋值给R0寄存器。
6,多寄存器寻址
多寄存器寻址一条指令最多能够完结16个通用寄存器值得传递
LDMIAR0,{R1,R2,R3,R4}
LDM是数据加载指令,指令的后缀IA表明每次履行完加载操作后R0寄存器的值自增1个子,ARM中一个字表明的是一个字的32位数字(bit),这条指令履行后,R1=[R0],R2=[R0+#4]
R3=[R0+#8],R4=[R0+#12]
7,仓库寻址
仓库寻址是ARM处理器特有的一种寻址方法,仓库寻址需求运用特定的指令来完结
仓库寻址的指令由LDMFA/STMFA,LDMEA/STMEA,LDMFD/STMFD
FA,EA,FD,ED 为指令前缀,表明多寄存器寻址,即一次能够传递多个寄存器值,FA,EA,FD,ED,为后缀
仓库寻址举例:
STMFD SP! {R1-R7,LR} @将R1~R7,LR入栈,多用于坚持子线程“现场”
LDMFD SP! {R1-R7,LR} @将数据出栈,放入R1~R7,LR寄存器,康复子程序“现场”
8,块复制寻址
块复制寻址能够完结接连地址数据从寄存器的莫某一方位复制到另一方位,
块复制寻址的指令由
LDMIA/STMIA,LDMDA/STMDA/LDMIB/STMIB
LDM和STM为指令前缀,表明多寄存器寻址,即一次能够传递多个寄存器值,IA,DA,IB,DB为后缀,
块复制举例
LDMIA R0! ,{R1-R3} @从R0寄存器指向的存储单元中读取3个子到R1-R3寄存器
STMIA R0! ,{R1-R3} @存储R1-R3寄存器的内容到R0寄存器指向的存储单元
9,相对寻址
相对寻址以程序计数器PC当时值为级地址,指令中的地址中的标号作为偏移量,将两者相加后得到操作数的有用地址
BL NEXT
…
NEXT :
….
BL NEXT 是跳转到NEXT标号处履行,这儿BL选用的便是相对寻址,标号NEXT 便是偏移量。
待续…