微波EDA网,见证研发工程师的成长!
首页 > 硬件设计 > 嵌入式设计 > ARM汇编 MOV PC,LR

ARM汇编 MOV PC,LR

时间:11-09 来源:互联网 点击:

  1. LABEL1:.word Value2

比如:

  1. _TEXT_BASE:
  2. .word TEXT_BASE

所对应的含义是,有一个标号_TEXT_BASE
而该标号中对应的位置,所存放的是一个word的值,具体的数值是TEXT_BASE,此处的TEXT_BASE是在别处定义的一个宏,值是0x33D00000。
所以,即为:
有一个标号_TEXT_BASE,其对应的位置中,所存放的是一个word的值,值为TEXT_BASE=0x33D00000。
总的来说,此种用法的含义,如果用C语言来表示,其实更加容易理解:
int *_TEXT_BASE = TEXT_BASE = 0x33D00000
即:
int *_TEXT_BASE = 0x33D00000

不过,对于这样的类似于C语言中的指针的汇编中的标号,在C语言中调用到的话,却是这样引用的:

  1. /* for the following variables, see start.S */
  2. extern ulong _armboot_start; /* code start */
  3. extern ulong _bss_start; /* code + data end == BSS start */
  4. 。。。
  5. IRQ_STACK_START = _armboot_start - CFG_MALLOC_LEN - CFG_GBL_DATA_SIZE - 4;
  6. 。。。

而不是我原以为的,直接当做指针来引用该变量的方式:

  1. *IRQ_STACK_START = *_armboot_start - CFG_MALLOC_LEN - CFG_GBL_DATA_SIZE - 4;


其中,对应的汇编中的代码为:

  1. .globl _armboot_start
  2. _armboot_start:
  3. .word _start

所以,针对这点,还是需要注意一下的。至少以后如果自己写代码的时候,在C语言中引用汇编中的global的标号的时候,知道是如何引用该变量的。

汇编中类似这样的代码:
label1: .word value2
就相当于C语言中的:
int *label1 = value2
但是在C语言中引用该标号/变量的时候,却是直接拿来用的,就像这样:
label1 = other_value
其中label1就是个int型的变量。
1.1.6. 汇编中的ldr+标号,来实现C中的函数调用
接着上面的内容,继续解释,对于汇编中这样的代码:
第一种:
ldr pc, 标号1
。。。
标号1:.word 标号2
。。。
标号2:
。。。(具体要执行的代码)
或者是,
第二种:
ldr pc, 标号1
。。。
标号1:.word XXX(C语言中某个函数的函数名)
的意思就是,将地址为标号1中内容载入到pc中。
而地址为标号1中的内容,就是标号2。
所以上面第一种的意思:
就很容易看出来,就是把标号2这个地址值,给pc,即实现了跳转到标号2的位置执行代码,就相当于调用一个函数,该函数名为标号2.
第二种的意思,和上面类似,是将C语言中某个函数的函数名,即某个地址值,给pc,实现调用C中对应的那个函数。
两种做法,其含义用C语言表达,其实很简单:
PC = *(标号1) = 标号2
举个例子就是:
第一种:

  1. 。。。
  2. ldr pc, _software_interrupt
  3. 。。。
  4. _software_interrupt: .word software_interrupt
  5. 。。。
  6. software_interrupt:
  7. get_bad_stack
  8. bad_save_user_regs
  9. bldo_software_interrupt


就是实现了将标号1,_software_interrupt,对应的位置中的值,标号2,software_interrupt,给pc,即实现了将pc掉转到software_interrupt的位置,即实现了调用函数software_interrupt的效果。
第二种:

  1. ldr pc, _start_armboot
  2. _start_armboot: .word start_armboot

含义就是,将标号1,_start_armboot,所对应的位置中的值,start_armboot给pc,即实现了调用函数start_armboot的目的。
其中,start_armboot是C语言文件中某个C语言的函数。

汇编中,实现函数调用的效果,有如下两种方法:
方法1:
ldr pc, 标号1
。。。
标号1:.word 标号2
。。。
标号2:
。。。(具体要执行的代码)
方法2:
ldr pc, 标号1
。。。
标号1:.word XXX(C语言中某个函数的函数名)
1.1.7. 汇编中设置某个寄存器的值或给某个地址赋值
在汇编代码start.S中,看到不止一处, 类似于这样的代码:
形式1:

  1. # define pWTCON0x53000000
  2. 。。。
  3. ldr r0, =pWTCON
  4. mov r1, #0x0
  5. str r1, [r0]

或者:
形式2:

  1. # define INTSUBMSK 0x4A00001C
  2. 。。。
  3. ldr r1, =0x7fff
  4. ldr r0, =INTSUBMSK
  5. str r1, [r0]

其含义,都是将某个值,赋给某个地址,此处的地址,是用宏定义来定义的,对应着某个寄存器的地址。
其中,形式1是直接通过mov指令来将0这个值赋给r1寄存器,和形式2中的通过ldr伪指令来将0x3ff赋给r1寄存器,两者区别是,前者是因为已经确定所要赋的值0x0是mov的有效操作数,而后者对于0x3ff不确定是否是mov的有效操作数
(如果不是,则该指令无效,编译的时候,也无法通过编译,会出现类似于这样的错误:

  1. start.S: Assembler messages:
  2. start.S:149: Error: invalid constant -- `mov r1,#0xFFEFDFFF
  3. make[1]: * [start.o] 错误 1
  4. make: * [cpu/arm920t/start.o] 错误 2


所以才用ldr伪指令,让编译器来帮你自动判断:
(1)如果该操作数是mov的有效操作数,那么ldr伪指令就会被翻译成对应的mov指令。
举例说明:
汇编代码:

Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top