0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

深度剖析ARM跳转指令

汽车电子技术 来源:宅学部落 作者:王利涛 2023-02-17 09:37 次阅读

跳转指令

顺序、选择、循环是构建程序的基本结构,任何一个逻辑复杂的程序基本上都可以由这三种程序结构组合而成。而跳转指令,则在子程序调用、选择、循环程序结构中被大量使用。程序的跳转是如何实现的呢?在了解这个机制之前,我们需要先了解一下程序计数器PC。

程序计数器PC,是CPU寄存器列表中最重要的一个寄存器。它就像一杆枪,指哪打哪:你给PC指针赋值哪个地址,CPU就会到PC指针指向的这个地址去取指令、翻译指令、执行指令。一般情况下,当你没有给PC指针赋新地址时,CPU在PC指针指向的地址取完指令后,PC计数器会自动加一,指向下一条指令,程序可以自动执行下去。当我们需要跳转时,可以直接给PC指针赋一个新地址,于是CPU就会跳转到新地址去执行了。

ARM中,常见的跳转指令有B、BL、MOV、LDR等。不同的指令,它们的使用条件、使用场合是不同的,今天就给大家总结一下它们的区别及各自使用的场合。

1B跳转指令

B指令是ARM中最基本的跳转指令,它的使用方法如下:

B label

上面语句表示跳转到label的标号处去执行。B跳转指令是ARM中最简单的指令,只是单纯的跳转,而且是相对跳转。它可以跳到以当前位置PC为基址,前后32MB的地址空间范围,所以B指令只是在临近的代码块、标号之间跳转。

B指令跳转,大多数时候是单向的,跳过去就不再返回来了。但是我们可以通过添加一些标号来实现一些控制逻辑:比如循环、选择程序结构:

;循环结构示例
LOOP
    SUB R0,R0,#1
    ...
    CMP R0,#0
    BNE LOOP
;选择结构示例
    MOV R1,#10
    MOV R2,#20
    CMP R1,R2
    BEQ HERE
    ...
    B END 
HERE
    ...
END
    ...

在上面的程序中,我们使用B跳转指令实现了选择、循环这两种基本的程序结构。B指令像ARM的其它指令一样,可以根据CPSR状态寄存器的标志位,有条件的执行。这样,可以减少指令数目、提高代码密度和运行效率。如BNE、BEQ就是当结果相等、不相等时的条件跳转。

当前程序状态寄存器:

图片

各种各样的条件码:

图片

2BL指令

BL指令跟B不同:在跳转之前,会先将当前指令的下一条指令地址保存到LR寄存器中,然后才跳转到标号执行。这样做的好处是:当我们想从标号地方返回时,可以直接将LR寄存器中的返回地址赋值给PC,程序就可以返回到原来的程序中继续执行了。

BL跳转指令一般用在子程序的调用中。无论是汇编语言子程序,还是C语言子程序,在跳转到子程序之前,都要将返回地址保存起来。当子程序执行完毕,将LR寄存器保存的返回地址,重新赋值给PC,处理器就可以返回到主程序继续执行了。

BEGIN
    MOV R0,#SRC
    MOV R1,#DST
    MOV R2,#100
    BL COPY
    NOP
    ...
 COPY
    SUB R2,R2,#1
    LDR R3,[R0],#1
    STR R3,[R1],#1
    CMP R2,#0
    BNE COPY
    MOV PC,LR

上面的汇编代码段,我们定义了一个汇编子程序COPY,实现了数据拷贝的功能。当我们使用BL指令调用这个子程序COPY时,CPU会首先将当前指令的下一条指令:NOP 的地址保存到LR寄存器中,然后才跳转到COPY子程序去执行。在COPY子程序中,处理完数据搬运后,通过

MOV PC,LR

这条语句,将保存在LR寄存器中的返回地址,重新赋值给PC,这样我们就可以返回到原来的程序中继续执行了。

在上面的汇编代码中,LR,即R14,连接寄存器,常用来存放程序的返回地址;PC,即R15,程序计数器,表示当前指令地址。LR和PC都是ARM汇编器为了方便程序员编程,预定义的一些宏。你在程序中使用这些助记符其实就是相当于操作R14和R15寄存器。除此之外,ARM中常用的助记符有:

  • FP:栈帧基址寄存器,即R12
  • SP:栈指针寄存器,即R13
  • LR:链接寄存器,即R14
  • PC:程序计数器,即R15

同样,在C语言调用子函数的过程中,在跳转子函数执行之前,CPU也会将当前指令的下一条指令地址保存到LR寄存器中,然后再跳转到子函数中执行。因为在子函数运行过程中,也有可能会用到ARM的一些寄存器,也有可能会调用其它的子函数,会覆盖掉保存在LR寄存器中的返回地址,所以,我们一般在运行子函数之前,会首先将LR寄存器压入子函数的栈帧,相当于将返回地址保存到了栈上。当子函数运行结束时,再通过出栈操作,将保存在栈中的返回地址弹出到PC指针中,这样程序就成功从子程序中返回了,直接返回到原来的函数中继续执行。

int main(void)
{
    func();
    printf("Hello!\\n");
    return 0;
} 
;对应的汇编代码
main
    BL func
    BL printf
func
    PUSH LR
    ...
    pop pc 
;func子函数返回

3MOV指令

通过上面的学习,我们可以看到,无论是B指令、还是BL指令,都是相对寻址。其本质都是以当前指令地址PC为基址,然后加上一个[0,32M]的偏移,达到修改PC的目的。

除此之外,我们也可以直接给PC指针赋值,达到跳转的目的。如上面的 func 子程序返回,就是直接通过

MOV PC,LR

这条指令,将LR寄存器中的返回地址,直接赋值给PC,直返回到原来的主函数去执行。

MOV指令主要用来在寄存器之间传输数据,或者将一个立即数传送到寄存器。但是MOV指令有一个硬伤,就是传递的立即数只能是8位数,有大小的限制。这是为什么呢?很简单,ARM是RISC架构,在一个32位的ARM中,指令通常都是32位的。而一个指令中,通常要包括操作码+操作数,如下图:

图片

一条指令,总共有32个bit空间,MOV这个操作码要占几位吧,Rd寄存器编码要占据几位吧,剩下的留给立即数的空间就不多了,所以这也就限定了MOV指令能传递的立即数的大小了。而一般的32位程序中,无论是变量还是函数,它们的地址一般都是32位的,如果使用MOV指令,将他们的地址传送到PC,使用下面的形式:

MOV PC,#0x30008000

你会发现,立即数#0X30008000这个地址就已经32位了,在加上MOV指令这个操作码,已经超过32位了,编译器是无法翻译这个指令的,所以说,当一个变量或函数地址为32位时,使用MOV指令给PC直接赋值,行不通,那怎么办呢?

4LDR伪指令

办法总是有的,比如,我们就可以通过伪指令LDR,直接将一个32位的立即数地址,传送到PC:

LDR PC,=0x30008000

LDR伪指令的功能和MOV一样,都可以将一个立即数传送到寄存器。唯一区别的就是,MOV指令只能传送8位的,而LDR可以传送一个32位的立即数或地址。

这里需要注意一下,立即数 0X30008000 的前面有一个等于号“=”,这表示前面的LDR指令是一个伪指令。除此之外,在ARM中,LDR还有另外一个意思,用来将内存中的数据加载到寄存器。我们知道,ARM是RISC架构,使用LDR/STR架构,不能直接修改内存中的数据。如果我们要修改内存中的一个变量,要首先使用LDR指令将内存中的变量加载到寄存器中,接着对寄存器进行操作,最后再使用STR指令将寄存器中的变量回写到内存中。所以,LDR可以看作是一个伪指令,也可以看做是普通的一个LDR指令,判定他们的区别就是看前面的等于号。

普通的LDR指令主要使用寄存器间接寻址,常用的使用方式如下:

LDR R0,[R1]
LDR R0,0x30008000

这里注意后面一句,是将地址0x30008000地址上的内容传动到寄存器R0,而不是直接将这个地址传送到R0,这里一定要注意其跟LDR伪指令的区别,这一点没有注意到,你在分析程序时就可能误入歧途了。

在《C语言嵌入式Linux高级编程》第二期中,我们已经探讨了CPU、指令集、伪指令的基本概念,这里就不赘述了。简单来说,伪指令并不是真正的ARM指令,并不属于ARM指令集中的标准指令。它只是编译器为了方便我们程序员开发程序,定义的一些助记符。在编译时,这些伪指令还是会使用指令集中的标准指令来实现。

比如上面的LDR伪指令,程序在编译时,看到这个伪指令,会使用ARM指令集中标准的指令实现。如果LDR伪指令中的立即数小于8位,它就会转换为MOV指令来实现:

LDR R0,=200
MOV R0,#200

如果LDR伪指令中,立即数大于8bit表示的数据范围,比如说是一个32位的立即数或地址,那就不能使用MOV指令来实现了,可以采用文字池的形式,先将这个地址常量单独存放在存储单元中,然后使用相对寻址,曲线救国,完成这个32位地址或立即数与寄存器之间的传输,这些细节在教程视频中都有讲到,就不再赘述了。

5小结

通过上面的学习,我们基本上理清了ARM系统中常见的几种跳转指令,以及它们的区别。只有彻底理解他们的底层机制及实现细节,才有可能在使用反汇编分析程序时,达到事半功倍的效果,从而大大提高我们的工作效率。否则,这些基本的细节和概念搞不清,将会永远成为你学习和工作上的障碍。

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 计数器
    +关注

    关注

    32

    文章

    2123

    浏览量

    92987
  • 程序结构
    +关注

    关注

    1

    文章

    6

    浏览量

    6897
  • 程序调用
    +关注

    关注

    0

    文章

    3

    浏览量

    799
收藏 人收藏

    评论

    相关推荐

    c语言深度剖析

    c语言深度剖析
    发表于 04-02 09:12

    C语言深度剖析

    C语言深度剖析
    发表于 08-25 09:08

    C语言深度剖析

    C语言深度剖析[完整版].pdfC语言深度剖析[完整版].pdf (919.58 KB )
    发表于 03-19 05:11

    arm汇编跳转指令总结

    目前所知道的跳转指令有 b,bl,bep,bne.他们共同点是都是以b开头,首先从字面上分析:b:是Branch,表示分支。bl:是Branch Link表示带连接的分支。bep:Branch
    发表于 04-26 02:39

    请问一下ARM跳转指令的范围是多少

    , ?]构造跳转指令。)B,BL指令保存的是偏移地址,这个地址的计算方法是:假设跳转指令处的地址是A,
    发表于 04-14 09:30

    请问一下ARM汇编中的B跳转指令和LDR跳转的区别在哪

    请问一下ARM汇编中的B跳转指令和LDR跳转的区别有哪些不同之处呢?
    发表于 07-21 15:57

    ARM汇编语言跳转指令的特殊用法还有吗

    关于 ARM汇编语言跳转指令的特殊用法。有如下两条跳转指令: beq lablefbeq lableb其中 lable 为某段程序的标号,b
    发表于 10-31 15:30

    arm汇编语言跳转指令有何特殊用法呢?

    关于 ARM 汇编语言跳转指令的特殊用法。有如下两条跳转指令: beq lablefbeq lableb其中 lable 为某段程序的标号,
    发表于 02-24 15:28

    arm指令集(1)

    arm指令集(1)  ARM跳转指令可以从当前指令向前或向后的32MB地址空间
    发表于 03-02 15:46 79次下载

    ARM指令集(2)

    ARM指令集(2)  1.跳转指令   在ARM中有两种方式可以实现程序的跳转:一种是刀
    发表于 03-02 15:49 68次下载

    Thumb指令集之Thumb跳转指令

    Thumb指令集中的跳转指令分以下6种类型。 ① 无条件跳转,其跳转空间为2KB。 ② 条件跳转
    发表于 10-19 10:04 1次下载
    Thumb<b class='flag-5'>指令</b>集之Thumb<b class='flag-5'>跳转</b><b class='flag-5'>指令</b>

    跳转指令B及带连接的跳转指令BLX上 

    跳转(B)和跳转连接(BL)指令是改变指令执行顺序的标准方式。ARM一般按照字地址顺序执行指令
    发表于 10-19 10:26 2次下载
    <b class='flag-5'>跳转</b><b class='flag-5'>指令</b>B及带连接的<b class='flag-5'>跳转</b><b class='flag-5'>指令</b>BLX上 

    ARM嵌入式系统的中断服务例程跳转

    在32位 ARM 系统中,一般都是在中断向量表中放置一条分支指令或PC寄存器加载指令,实现 程序跳转 到 中断服务 例程的功能。例如: IRQEntry B HandleIRQ ;
    发表于 04-10 10:11 2674次阅读

    PLC跳转/标号指令的工作原理及应用举例

    跳转/标号执行是用来跳过部分程序使其不执行必须用在同一程序块内部实现跳转跳转/标号指令有两条,分别为跳转
    的头像 发表于 10-08 09:59 4212次阅读

    西门子博途SCL的GOTO跳转指令

    跳转标签和“跳转指令必须在同一个块中。在一个块中,跳转标签的名称只能指定一次。每个跳转标签可以是多个
    发表于 07-03 14:53 5033次阅读