[中级教程]GNU ARM汇编程序开发之----几个常用的指令

来源:互联网 发布:手机上怎么看淘宝等级 编辑:程序博客网 时间:2024/06/03 23:04

我写这边文章,不是为了别的,而是写给自己看,写给这个时候清楚,而他日可能忘记的自己,如果你无意中看到了,甚至觉得对自己有点启发,那算是上帝的旨意吧。

前言

在搞嵌入式设备开发的过程中,汇编程序设计,作为一个顶着中级以上的职称的,必须要懂,否则,也没有什么否则啦。就目前来说,两个主流的开发环境:基于Window基于Linux这两大平台。

  • window下一般如单片机开发的,会使用一些集成开发环境,比如MDK-ARM这种。
  • 基于Linux平台的一般没有IDE,多是自己打造IDE,比如, 文本编译器VIM,交叉编译工具链arm-linux-gcc,自己编写Makefile等。

而今,大部分的主流的芯片官方都会推出一些类似的DEMO板,并在U-BOOT,或者Linux内核中提供样板的支持,不过这些也仅仅只是满足一些较为常见的设备类的,高端的公司,一般不会向社会公布自己使用的核心技术板,你要想在这些高端的公司生存下去,而不是去玩弄那些U-BOOT或者Linux源码中支持的那些简单的样板,你得掌握比别人更加优秀的开发能力。

更何况,Linux内核也好,U-Boot也好,他们不会为每个未知的设备都提供样板支持,公司如果给你一块板子,而你发现U-BOOT工程中并不支持这个板子,那怎么办,有可能就慌了,这时的嵌入式开发人员要懂得自己如何实现一个类U-Boot的工程非常的有必要,掌握这些实现的主干,不管是什么的板子,你都能在U-BOOT中实现对它的支持。今天,就start.S中几个经常出现的指令,做一些简单的说明,至少让你看到,就知道什么意思。

小知识点

  • window的汇编编程风格是遵从INTEL的汇编编程规范,最强的特征就是,汇编指令全用大写(非常重要)
  • Linux下的汇编编程风格是遵从AT&T的会变成编程规范,最强的特征就是,汇编指令全用小写(非常重要)
  • 基于Window平台的嵌入式开发,所使用的编译器往往是ARMCC,对汇编程序的编译使用的是ARM asm,也就是完全符合ARM指令集标准的编译器。(非常特别重要)
  • 基于Linux平台的,却不是如window平台的那样,所使用的编译器往往是arm-linux-gcc,他们使用的GNU asm, 该汇编器不完全符合ARM标准的语法,甚至多数地方是不同的,所以,在Linux平台下写汇编程序,要记得区分。(非常特别重要)

有上面几句话下肚,在汇编程序开发过程中,出现问题时,便应该懂得去找什么样的手册或者文档去阅读,而不是眉毛胡子一把抓,逮着这汇编文档就看,到最后程序编译还是通不过。

接下来,我们讲解几个指令

1.bic指令

指令格式:

bic Rd, op1, op2

op2,是一个32位的掩码,说白了,也就是个32bit的数,每个bit如果你写1,bic就会清掉这一位

注解:
就是将op1 & (op2的反码)值送回到Rd寄存器中去。

举例:
在u-boot中,我们经常见到这样的一段代码

    .globl resetreset:    mrs r0, cpsr    bic r0, r0, #0x1f    orr r0, r0, #0xd3    msr cpsr, r0    

研究过U-boot的人,都懂这段代码的意思是设置系统进入SVC32的模式,那么对于新手,这里的bic的作用是个例子,

bic r0, r0, #0x1f

意思就是将r0寄存器中的值,低5位全清0,而其他位保持不变。

2.orr指令

指令格式:

orr Rd, op1, op2

op2,是一个32位的掩码,说白了,也就是个32bit的数,每个bit如果你写1,orr就会置一这一位

注解:
就是将op1 | op2 值送回到Rd寄存器中去。

举例:
还是拿刚才u-boot中的设置svc32模式的代码来说

    .globl resetreset:    mrs r0, cpsr    bic r0, r0, #0x1f @clear bit0~bit4    orr r0, r0, #0xd3 @set bit0,bit1,bit4,bit5,bit7    msr cpsr, r0    

研究过U-boot的人,都懂这段代码的意思是设置系统进入SVC32的模式,那么对于新手,这里的orr的作用是个例子,

orr r0, r0, #0xd3

意思就是将r0寄存器中的第0位,第1位,第4位,第5位,第7位置一,其他位全部不变。为啥是上面几位,因为0xd3的二进制值就是10110011’b。

3.ldr

ldr指令在GNU arm中是属于特殊的存在,因为它即可以当成内存访问指令来用,也可以当成伪指令来用,比如说,

ldr r0, =0x5300000ldr r1, =0x0000ffffstr r1, [r0]

这段代码是设置关闭2416芯片的看门狗,0x53000000是看门狗配置寄存器的地址,这里的“=”号便是对这条ldr指令的伪指令说明,也就是看到了ldr中有这样的用法,那就是明显的在当成伪指令用。伪指令的用意就是将=后面的值直接放入到寄存器中去。

0 0