摘要:
第一篇csdn日志,记录今天为了学习汇编而配置开发环境的过程,解决了一些疑问点和坑,上传以供分享、学习、交流。
两种模拟环境配置方式:
为方便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版本之间不兼容(具体详细原因不明)。
相关工具:
交叉编译工具链 arm-2011.09-70-arm-none-linux-gnueabi – 针对ARM的编译源码的工具
keil(mdk) – 用于源码编辑、调试的工具。
配置步骤:
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__ = .;
}
参考: