Arm汇编学习笔记(二)——编写编译并执行依赖外部模块的汇编代码以及PIC代码分析
来源:互联网 发布:集成吊顶计算软件 编辑:程序博客网 时间:2024/06/06 19:58
1. 编译依赖外部模块的汇编代码并执行
- 创建test.S汇编文件,并输入如下内容:
.global main.extern printf.textmain:stmfd sp!, {r11, lr}ldr r0, =strbl printfldmfd sp!, {r11, pc}.datastr:.asciz "Hello asm\n".end
上面代码调用到了libc库中的printf函数。
- 输入下面命令编译成目标文件
arm-linux-androideabi-as test.S -o test.o得到test.o目标文件。
- 输入下面命令编译成可执行文件
arm-linux-androideabi-ld test.o ~/Softwares/Android/android-ndk-r9d/platforms/android-19/arch-arm/usr/lib/crtbegin_dynamic.o ~/Softwares/Android/android-ndk-r9d/platforms/android-19/arch-arm/usr/lib/crtend_android.o -l ~/Softwares/Android/android-ndk-r9d/platforms/android-19/arch-arm/usr/lib/libc.so -I /system/bin/linker -o test.out得到可执行文件test.out,将其push到android设备中运行可以打印出Hello asm字符串。
2. PIC位置无关代码分析
在上面的例子中我们编写的汇编代码实际上使用的是位置相关代码,首先看一下位置无关以及位置相关代码的定义。
位置无关码:CPU取指时,总是相对于本条执行指令的相对地址去取指。比如指行一个ADD指令时,PC要取下一指令的地址,就在原来的基础上+4。这就不管你代码放在存储器的任何位置,只要他们的相对地址没有改变,就能正常执行程序。位置相关码:可以这样来说,就是CPU每次取指都从绝对位置去取,而不是上面的相对位置。这个绝对地址就是相对起始地址0来说的。这样,就要求你在存放程序时,必须给连接脚本所规定的一样,把代码放到指定位置。
我们上面的例子中在给printf传递参数的时候用到了str,即"Hello asm\n"字符串的绝对地址(str是汇编代码中代表字符串的标签,这里只是为了方便大家看,包括所有的编程语言的符号都一样,在实际的机器代码中是没有这些标签和符号的,有的只有数据和地址)。在代码链接成可执行文件的时候str会被分配一个地址,但是如果在加载到内存中的时候内存地址与被分配的地址不一样,那么在运行的过程中就会出错。所以一般在我们编程的过程中都会加上一个编译参数-fPIC,生成位置无关的代码。
下面我们举一个位置无关的例子给大家看,看下面的C代码:
#include <stdio.h>int main(void){ printf("Hello CrossCompile\n"); return 0;}gcc编译生成可执行文件后我们通过ida查看其汇编代码如下图:
可以看到其汇编代码中是如何为printf传递参数的,基本上是下面三条语句
LDR R3, =(aHelloCrosscomp - 0x8298)ADD R3, PC, R3 ;MOV R0, R3 ;而aHelloCrosscomp的定义是在rodata段中,如下图:
上面的语句到底是什么意思呢?仔细分析一下就可以知道,所谓位置无关的代码就是要访问相对地址,不管可执行文件加载到内存中的任何位置,可执行文件内部的数据和指令之间的相对位置是绝对一致的,我们就可以利用这一点,通过要访问的数据的地址与当前pc值即当前指令地址之间的差值得到这个相对偏移。
那为什么在main函数后面会有"off_82A8 DCD aHelloCrosscomp - 0x8298"这样的一个数据定义呢?原因很简单,因为一条ARM指令只有32位,而aHelloCrosscomp的位置有可能很大,一条指令是放不下的,而地址的相对偏移是固定的,在编译阶段就可以确定,所以编译器直接算好了在text段函数的后面定义了一个临时的内部的数值。一定是通过pc值加上这个相对偏移,得到字符串的最终地址存储在寄存器中,而不能直接拿字符串的32位的地址去操作,一条ARM指令放不下这么多数据。
那为什么是aHelloCrosscomp - 0x8298呢?这个0x8298是怎么得到的呢?我们看代码中,真正将当前指令与相对偏移计算得到字符串地址的指令是".text:00008290 ADD R3, PC, R3"这条指令,它的地址是0x8290,而我们根据CPU三级流水线的原理知道,在执行到这条指令的时候,已经去加载后面第二条指令了,这时候pc的值是当前指令地址+0x8才对,即0x8298。这是非常重要的,要谨记!!
就分析这么多,如有错误,欢迎指正!
0 0
- Arm汇编学习笔记(二)——编写编译并执行依赖外部模块的汇编代码以及PIC代码分析
- Arm汇编学习笔记(一)——编写编译并执行简单汇编文件
- arm汇编文件编译以及代码查看
- 《Linux内核分析》(一)——反汇编一个简单的C程序并分析其汇编代码的执行
- ARM 汇编学习——编写简单的ARM汇编程序
- ARM 汇编学习——编写简单的ARM汇编程序
- ARM 汇编学习——编写简单的ARM汇编程序
- 《网络渗透技术》学习笔记(2)——一段简单的汇编代码分析 zz
- Arm汇编学习笔记(九)——高效的分支代码及非对齐数据的访问
- 结合Bootloader的相关知识,并参考ARM的汇编指令,分析下面的Bootloader代码。
- VS2005混合编译ARM汇编代码
- 转:VS2005混合编译ARM汇编代码
- Linux汇编代码学习,反汇编简单的c及分析汇编代码工作过程
- Arm汇编学习笔记(三)——GCC内联汇编
- ARM汇编配置重启代码分析
- 汇编环境配置以及代码编写调试
- ARM汇编代码格式
- 优龙Bootloader ARM汇编代码笔记
- 中国天气网API接口
- hdu 2068 RPG的错排
- 单例模式(四)
- 酒鬼
- 记一次JVM内存调整
- Arm汇编学习笔记(二)——编写编译并执行依赖外部模块的汇编代码以及PIC代码分析
- Java反射知识总结
- 敏捷开发之Scrum框架入门
- Myeclipse自动生成javabean的get和set方法
- BS开发仅支持32位runtime
- Ubuntu 修改 ssh远程端口号
- PCA算法的理解,和在kneans中的运用
- 揭秘:Linux centos 安装操作说明
- AOS 自动生成代码功能实现