ARM 汇编指令学习笔记之点亮LED灯
众所周知汇编是比较底层的语言,它相较于其他高级语言更能直观的体现出程序和硬件之间的关系。我以控制一个LED为目标开始我的汇编学习之路,我用的Cortex-A内核的汇编指令,用的交叉编译器是GCC交叉编译器。
- 汇编语句的组成部分:adress:command#comment; 该语句通过“:”分为两部分,“:”前面部分表示地址标号,通过该标号可以找到该该指令下的地址,“:”后面部分“command”表示这条语句要执行的动作,“#"后面的内容为该条语句的注释。
[80x86汇编语言程序设计教程]有提及这句话:
"通常情况下,代码和数据分别在代码段和数据段中,但有时代码和数据可以合并在一个段中.一个完整的汇编语言源程序至少含有一个代码段,但一个汇编语言源程序模块却可以只有数据段.目前,我们总把数据段安排在程序的前面,把代码段安排在程序的后面,但不是非要这样安排."
用户可以使用.section伪操作来定义一个段,即——段,每个段以段名开始,以下一段名或者文件结尾结束汇编系统预定义了一些段名:
1).text:表示代码段;
2).data:表示初始化的数据段;
3).bss:未初始化的数据段;
4).sodata:只读数据段;
汇编程序的默认入口标号是_start,使用如下所示
.global _start _start: ldr r0,=0x12 #r0=0x12
代码中.global是伪操作,表示_start是一个全局标号。
- 上面介绍了一条指令的编写格式,下面介绍函数格式:
函数名:
函数体
返回语句#返语句不是必须的
在控制LED的过程中当然少不了对GPIO的寄存器的控制,这里主要用到STR和LDR两条寄存器访问指令。
1)LDR主要用来从指定地址加载数据到寄存器Rx中,示例代码如下:
LDR R0 ,=0x0209c004@将寄存器地址0x0209c004加载到R0中,即R0=0x0209c004
LDR R1,[R0]@读取地址0x0209c004中的数据到R1寄存器中
2)STR主要用来将数据写到寄存器中,示例代码如下:
LDR R0,=0x0209c004 @将寄存器地址0x0209c004加载到R中,即R0=0x0209c004 LDR R1,=0x20000002 @R1保存要写到寄存器的值,即R1=0x20000002 STR R1,[R0] @将R1中的值写入到R0中所保存的地址中
LDR 和STR都是按照字进行读写寄存器的,如果要按照字节,双字节进行读写时,可以在指令LDR和STR后面加上B或H,比如按字节操作就是LDRB和STRB,按双字节进行读写就用LDRH 和STRH。
- 实验程序的编写
对所用到GPIO的配置如下:
1)使能GPIO时钟
.global _start _start: ldr r0, =0X020C4070 /* CCGR2 */ ldr r1, =0XFFFFFFFF /*使能GPIO3外设时钟*/ str r1, [r0]
2)设置GPIO1复用为GPIO1_IO3
ldr r0, =0X020E0068 /* 将寄存器SW_MUX_GPIO1_IO03_BASE加载到r0中 */ ldr r1, =0X5 /* 设置寄存器SW_MUX_GPIO1_IO03_BASE的MUX_MODE为5 */ str r1,[r0]
3)配置PGIO1_IO3属性
ldr r0, =0X020E02F4 /*寄存器SW_PAD_GPIO1_IO03_BASE */ ldr r1, =0X10B0 str r1,[r0]
4)设置GPIO1_IO3方向
ldr r0, =0X0209C004 /*寄存器GPIO1_GDIR */ ldr r1, =0X0000008 /*输出*/ str r1,[r0]
5)打开LED0
ldr r0, =0X0209C000 /*寄存器GPIO1_DR */ ldr r1, =0 /*设置低电平*/ str r1,[r0]
6)loop死循环
loop: b loop /*这里用到一个指令B:用来跳转到指定位置*/
以上就是点亮一个LED的全部汇编代码。^-^

浙公网安备 33010602011771号