本文主要介绍关于ARM汇编程序在ubuntu虚拟机中进行仿真及程序调试的相关介绍:
所需要的工具:
①装有ubuntu(linux)的虚拟机
②安装了qemu仿真器(一款主要仿真ARM CPU的软件)
③安装了交叉编译工具链(本人安装的是arm-none-linux-gnueabi-系列的4.6.4版本交叉编译工具链)
下面以mrs和msr ARM汇编指令的一个小程序来进行演示(暂时叫做CPU的状态切换吧)
第一步:安装qemu仿真器
设置网络,保证能够连通百度;
1、sudo apt-get update
2、sudo apt-get install qemu qemu-system qemu-utils
3、qemu-system-arm --h 该条语句为测试是否安装成功,可不进行执行
第二步:安装交叉编译工具链
1、解压gcc-4.6.4.tar.xz
tar -xvf gcc-4.6.4.tar.xz
2、扩展该交叉编译工具链的路径
①为什么要使用交叉编译工具链?
因为我们要编译在ARM芯片上跑的程序,而我们使用x86平台下系统自带的gcc编译的话,就是x86平台下的编译程序,不同平台最终编译出来的程序的机器码不一样,所以必须要使用交叉编译工具链。
②为什么要扩展交叉编译工具链的路径?
其实这个包解压后,在这个包的bin目录下有很多进行编译链接的工具,但是因为这些工具没有包含到系统自动检测的路径中,所以我们只能在当前的bin目录下使用这些工具,在别的目录下就必须使用路径+该工具的形式才能进行程序的编译,这样非常不方便,所以需要将这些工具的检索路径添加到系统的搜索路径中,也就是拓展PATH环境变量的值。
③具体步骤
a.进入到~目录下,打开.bashrc
b.在打开文件的末尾拓展环境变量值
注意自己交叉编译工具链的路径,这里因为我自己安装了两个版本的交叉编译工具链,所以对PATH环境变量进行了两次值的拓展;拓展之后要将该shell脚本执行一遍,之后环境变量才会导入PATH中,成功的标志是执行命令echo $PATH之后会在PATH环境变量的自动检索路径中看到我们添加的路径。
第三步:交叉编译工具编译ARM汇编程序
测试的汇编代码如下:
.global _start
_start:
mrs r0, cpsr
bic r0, #0x1f
orr r0, #0x12
msr cpsr, r0
nop
b end
.end
Makefile编译脚本如下:
mrs.elf: mrs.o
arm-linux-ld -Ttext 0x0 -o mrs.elf $^
%.o : %.S
arm-linux-gcc -o $@ $< -g -c
clean:
rm *.o *.elf -f
该编译脚本其本质可拆分为下面两条指令:
arm-linux-gcc test.S -o mrs.o -c -g //注意:-g参数是为了后面进行gdb调试使用
arm-linux-ld -Ttext 0x00000000 test.o -o mrs.elf
第四步:qemu仿真调试
1、编译成功之后生成.elf的可执行文件,运行qemu仿真器
qemu-system-arm -machine vexpress-a9 -m 256M -serial stdio -kernel mrs.elf -S -s
注:因为我自己为了以后重复敲这行代码,将该命令写在一个脚本中的,所以会出现bash相关显示,直接敲命令的时候没有这些显示,只会弹出一个qemu的黑框。
2、执行交叉编译工具链中的gdb调试工具
①再开一个终端执行下面命令
arm-none-linux-gnueabi-gdb mrs.elf
②输入 target remote localhost:1234 命令来连接qemu
注:这个时候就相当于qemu是一个远程的ARM开发板,然后我们gdb通过网络连接着这个远程开发板进行程序调试实验。其中localhost为主机ip,因为我是在本机实验所以是localhost,端口号是1234
3、gdb调试相关指令
l 表示查看当前程序,将其打印到终端
b 表示设置断点(注:因为汇编程序运行非常快,所以需要有一个nop指令在.end前,否则会出现断点设置不成功)
c 表示程序继续执行,一直运行到断点处
s 表示进行单步运行
x /字节数 内存起始地址 用于查看一片内存中的数据
p $寄存器名 用于查看寄存器中的值
q 退出gdb调试
因为自己做的是一个ARM状态切换的验证程序,所以进行的是,读CPSR的值,然后改CPSR的值,最后回写CPSR的值,CPU自动切换状态,只要验证切换前后cpsr寄存器中CPRS的值的后五位不同其他位相同即成功。
可以看到切换前后cpsr后五位的值确实变化了,证明状态切换成功。