您的位置 首页 报告

ARM汇编 MOV PC,LR

终于明白这个LR寄存器了看下面这个ARM汇编吧BLNEXT;跳转到子程序………;NEXT处执行NEXT……….MOVPC,LR;从子程序返回这…

总算了解这个LR寄存器了

看下面这个ARM汇编

BL NEXT ;跳转到子程序

……… ;NEXT处履行

NEXT

……….

MOV PC,LR ;从子程序回来

这儿的BL是跳转的意思,LR(R14)保存了回来地址

PC(R15)是当时地址,把LR给PC便是从子程序回来

这儿有一下总结

首要

1.SP(R13) LR(R14)PC(R15)

2.lr(r14)的作用问题,这个lr一般来说有两个作用:
1》.当运用bl或许blx跳转到子进程的时分,r14保存了回来地址,能够在调用进程结束康复。
2》.反常中断产生时,这个反常办法特定的物理R14被设置成该反常办法即将回来的地址。

别的留意pc,在调试的时分显现的是当时指令地址,而用mov lr,pc的时分lr保存的是此指令向后数两条指令的地址,咱们能够试一下用mov pc,pc,成果得到的是跳转两条指令,这个原因是因为arm的流水线形成的,预取两条指令的成果.

3.》我曾经看书不明白的当地

子程序回来的三种办法

现在总结如下

1.MOV PC,LR

2.BL LR

3.在子程序入口处运用以下指令将R14存入仓库

STMFD SP!,{,LR}

对应的,运用以下指令能够完结子程序的回来

LDMFD SP!, {,LR}

转载自:http://blog.csdn.net/xgx198831/article/details/8333446

汇编学习总结记载

1.1. 汇编学习总结记载
关于咱们之前剖析的start.S中,涉及到许多的汇编的句子,其间,能够看出,许多包含了许多种不同的语法,运用常规等,下面,就对此进行一些总结,借 以完成必定的举一反三或许说举一反三,这样,能够起到必定的学习功用,便利今后看其他相似汇编代码, 简单看懂汇编代码所要表达的意义。
1.1.1. 汇编中的标号=C中的标号
像前面汇编代码中,有许多的,以点最初,加上一个姓名的办法的标号,比方:

  1. reset:
  2. /*
  3. * set the cpu to SVC32 mode
  4. */
  5. mrs r0,cpsr

中的reset,便是汇编中的标号,相对来说,比较简单了解,就相当于C言语的标号。
比方,C言语中界说一个标号ERR_NODEV:

  1. ERR_NODEV: /* no device error */
  2. … /* c code here */

然后对应在别处,运用goto去跳转到这个标号ERR_NODEV:

  1. if (something)
  2. goto ERR_NODEV ;

汇编中的标号 = C言语中的标号Label
1.1.2. 汇编中的跳转指令=C中的goto
对应地,和上面的比方中的C言语中的编号和掉转到标号的goto相似,汇编中,关于界说了标号,那么也会有对应的指令,去跳转到对应的汇编中的标号。
这些跳转的指令,便是b指令,b是branch的缩写。
b指令的格局是:
b{cond} label
简单说便是跳转到label处。
用和上面的比方相关的代码来举例:

  1. .globl _start
  2. _start: b reset

便是用b指令跳转到上面那个reset的标号。

汇编中的b跳转指令 = C言语中的goto
1.1.3. 汇编中的.globl=C言语中的extern
关于上面比方中:

.globl _start
中的.global,便是声明_start为全局变量/标号,能够供其他源文件所拜访。
即汇编器,在编译此汇编代码的时分,会将此变量记下来,知道其是个全局变量,遇到其他文件是用到此变量的的时分,知道是拜访这个全局变量的。
因而,从功用上来说,就相当于C言语用extern去生命一个变量,以完成本文件外部拜访此变量。

汇编中的.globl或.global = C言语中的extern
1.1.4. 汇编顶用bl指令和mov pc,lr来完成子函数调用和回来
和b指令相似的,别的还有一个bl指令,语法是:
BL{cond} label
其作用是,除了b指令跳转到label之外,在跳转之前,先把下一条指令地址存到lr寄存器中,以便利跳转到那儿履行结束后,将lr再赋值给pc,以完成函数回来,持续履行下面的指令的作用。
用下面这个start.S中的比方来阐明:

  1. bl cpu_init_crit
  2. 。。。
  3. cpu_init_crit:
  4. 。。。
  5. mov pc, lr

其间,便是先调用bl掉转到对应的标号cpu_init_crit,其实便是相当于一个函数了,
然后在cpu_init_crit部分,履行结束后,最终调用 mov pc, lr,将lr中的值,赋给pc,即完成函数的回来原先 bl cpu_init_crit下面那条代码,持续履行函数。
上面的整个进程,用C言语表明的话,就相当于

  1. 。。。
  2. cpu_init_crit();
  3. 。。。
  4. void cpu_init_crit(void)
  5. {
  6. 。。。
  7. }

而关于C言语中,函数的跳转前后所要做的工作,都是C言语编译器帮咱们完成好了,会将此C言语中的函数调用,转化为对应的汇编代码的。
其间,此处所说的,函数掉转前后所要做的工作,便是:
函数跳转前:要将当时指令的下一条指令的地址,保存到lr寄存器中。
函数调用结束后:将之前保存的lr的值给pc,完成函数跳转回来。持续履行下一条指令。
而假如你自身自己写汇编言语的话,那么这些函数跳转前后要做的工作,都是你程序员自己要关怀,要完成的工作。

汇编中bl + mov pc,lr = C言语中的子函数调用和回来
1.1.5. 汇编中的对应方位有存储值的标号 = C言语中的指针变量
像前文所解析的代码中相似于这样的:

  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指令。
举例阐明:
汇编代码:

  1. # define pWTCON0x53000000
  2. 。。。
  3. ldr r0, =pWTCON

被翻译后的真实的汇编代码:

  1. 33d00068: e3a00453mov r0, #1392508928 ; 0x53000000

(2)假如该操作数不是mov的有用操作数,那么ldr伪指令就会被翻译成ldr指令。
举例阐明:
汇编代码:

  1. ldr r1, =0x7fff

被翻译后的真实的汇编代码:

  1. 33d00080: e59f13f8ldr r1, [pc, #1016] ; 33d00480
  2. 。。。
  3. 33d00480: 00007fff.word 0x00007fff

即把ldr伪指令翻译成真实的ldr指令,而且别的分配了一个word的地址空间用于寄存该数值,然后用ldr指令将对应地址中的值载入,赋值给r1寄存器。

汇编中,一个常用的,用来给某个地址赋值的办法,相似如下办法:

  1. #define 宏的姓名寄存器地址
  2. 。。。
  3. ldr r1, =要赋的值
  4. ldr r0, =宏的姓名
  5. str r1, [r0]

声明:本文内容来自网络转载或用户投稿,文章版权归原作者和原出处所有。文中观点,不代表本站立场。若有侵权请联系本站删除(kf@86ic.com)https://www.86ic.net/ceping/baogao/277045.html

为您推荐

联系我们

联系我们

在线咨询: QQ交谈

邮箱: kf@86ic.com

关注微信
微信扫一扫关注我们

微信扫一扫关注我们

返回顶部