【嵌入式-环境配置】ARM9汇编 模拟环境配置

摘要:
第一篇csdn日志,记录今天为了学习汇编而配置开发环境的过程,解决了一些疑问点和坑,上传以供分享、学习、交流。

两种模拟环境配置方式:

1、Qemu 模拟器:

为方便C开发编程,在Ubuntu 12.04LTS下安装qemu模拟器来模拟arm开发环境:

sudo apt-get install qemu qemu-system

测试安装结果:

qemu-system-arm -version

在12.04Lts版本下,安装的是qemu1.0.50版本,编译执行链接过程顺利执行过后,汇编测试结果正常。

在16.04Lts版本下,安装的是qemu2.5.0版本,编译执行链接过程顺利执行过后,汇编测试结果异常,主要现象是汇编的STR 指令失效:

str r0,[r1] //r0中的数值并没有存储到r1存储的地址空间中

原因可能是qemu和新的ubuntu版本之间不兼容(具体详细原因不明)。

2、keil(mdk):

相关工具:

交叉编译工具链 arm-2011.09-70-arm-none-linux-gnueabi – 针对ARM的编译源码的工具

keil(mdk) – 用于源码编辑、调试的工具。

配置步骤:

  1. 安装交叉编译工具链
  2. 安装Keil(mdk)开发工具,注意packs的路径
  3. 官网 http://www.keil.com/dd2/ 下载 离线支持包并安装
  4. 官网 http://www2.keil.com/mdk5/legacy 下载Legacy device database(旧设备数据库)
  5. 创建新的uVision工程,新建空白文件(start.s),编辑汇编代码,作为已存在文件添加进当前Group
  6. 选中当前Target,打开管理项目对话框,勾选Use Gcc,并设置prefix(- 易漏)和Folder(推荐打开交叉编译文件根目录并复制粘贴目录)
  7. 拷贝map.lds链接脚本到当前test01.uvprojx文件目录下,打开Options for target对话框选中linker选项卡,设置linker script file为test目录下的map.lds
  8. (易漏)选择Debug选项卡中的Use Simulator模式。

tips:

1、编译出错 - 非常迷的一点,设置GCC编译后,rebuild提示错误

--- Error: failed to execute 'arm-none-linux-gnueabi-gcc'

然后切换为ARMCC后,rebulid正常报错;错了就换回来吧,等重新又选择GCC编译并编译运行后,0 error,0 waring。

keil真的无话可说,活脱脱花了二十分钟排错。

2、调试出错 - 开始debug的时候,内存起始地址0x00000000以后的指令都是

addeq r0,r0,r0

而点击跳转到start.s的第一条指令,在像0x000008ef左右的地址上,非常奇怪。

回顾检查前面的操作,编译成功的条件下,原来链接脚本设置那块默认又清空了
在这里插入图片描述
就是这个地方,清空了,按照正常步骤添加回去就好了,然后重新debug,发现start.s文件第一条指令就在0x00000000

3、如果调试出现*** error 65: access violation at C:0xFFA7 : no ‘execute/read’ permission,大概率是地址设置出错了,查看lds链接脚本或Linker scrpit设置大概率能解决这个问题。如果不行,就试试debug模式下的地址映射吧。再不济,检查下Options中的Debug下dll的设置,应该能解决(不能解决又能怎样呢?笑~)

4、keil的错误: Error: Encountered an improper argument

遇到第四个错误真的是瑟瑟发抖,算是最后的BOSS了吧。弹窗提示关不完,资源管理器把keil5进程杀了,重新打开就可以了。网上说是设置的断点没清理干净,大概率是这样的,算是keil新版本的BUG吧。

为什么这么说?因为在测试过程中,设置了断点同样遇到这个问题,不过干脆就kill了进程重启,没有太深刻的印象了。

最后:

综上流程和问题都处理清楚后,编译的汇编程序在debug下正常完美地跑起来。中途无数次,从疑惑到崩溃,从崩溃到一线希望,随后再崩溃,再蒙圈,感觉成功就是那么0.01的概率,keil你告诉我,我跑起来是不是在你的预料之外,天知道运行顺利是不是keil的BUG呢。

开个玩笑,小心翼翼地调试检测,明白其中原理,就会好很多了,加油吧优衣酱,go!!

最后的最后,补上lds模板,希望有人能用到(这里是地球。不要回答,不要回答!)

模板一

OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm") /*   指定输出的文件格式     */
OUTPUT_ARCH(arm) 		/* 	生成文件支持arm系列的CPU     */
ENTRY(_start) 			/*  连接后的第一条指令所在的地址是_start  */
SECTIONS 		    	/*  目标文件的摆放    		*/
{
	. = 0x00;  	/*  指定链接的起始地址   	*/
	. = ALIGN(4);    	/*  指令的对齐     			*/
	.text      : 	 	/*  代码段的开始     		*/
	{
		start.o(.text) 	/* 	start.o文件放在开始的位置   */
		*(.text)        /* 	其他目标文件自动分配位置    */
	}
	. = ALIGN(4);  		/* 	代码的对齐*/
    .data : 
	{ *(.data) }
    . = ALIGN(4);
    .bss :
     { *(.bss) }
}


板二

/*链接脚本文件:编译器解析链接脚本文件中的信息,
决定最终代码中各类数据在内存中的排布,
以及可执行代码的格式*/
/* 输出可执行文件的格式 : 32位elf文件,arm小端对齐*/
OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm")
/*OUTPUT_FORMAT("elf32-arm", "elf32-arm", "elf32-arm")*/
/* 输出架构 :ARM架构*/
OUTPUT_ARCH(arm)
/* 入口 :_start函数*/
ENTRY(_start)
/* C代码在内存中的排布 */
SECTIONS
{
. = 0x00000000; /* 代码的入口地址为0x0*/
. = ALIGN(4); /* 对齐*/
.text : /* 代码段 */
{
/*将.o文件链接成.elf文件时,
将start.o放在代码段最开始的位置 */
./Objects/start.o(.text) /* 启动文件 */
/* 其他的.o文件编译器决定如何排布*/
*(.text)
}
. = ALIGN(4);
.rodata : /*只读数据段 */
{ *(.rodata) }
. = ALIGN(4);
/* 已经初始化的全局变量,
或者使用使用static修饰的局部变量并且初始化*/
.data :
{ *(.data) }
. = ALIGN(4);
__bss_start = .;
/* 未初始化的全局变量,
或者使用使用static修饰的局部变量并且未初始化*/
.bss :
{ *(.bss) }
 
__bss_end__ = .;
}

参考:

  1. 解析map.lds文件
  2. ARM9汇编 模拟环境配置

你可能感兴趣的:(汇编,arm)