arm汇编中的跳转指令

发布者:bemaii最新更新时间:2016-05-09 来源: eefocus关键字:arm汇编  跳转指令 手机看文章 扫描二维码
随时随地手机看文章
ARM汇编中,常有两种跳转方法:b跳转指令、ldr指令向PC赋值。
我自己经过归纳如下:
(1)b label
该 指令完成的操作是pc<-label,将label处的地址传给pc。b跳转指令是相对跳转,依赖当前PC的值,偏移量是通过该指令本身的 bit[23:0]算出来的,这使得使用b指令的程序不依赖于要跳到的代码的位置,只看指令本身。即该分支指令的二进制码的后24位的实际的值是相对当前 的 R15 的值的一个偏移量;而不是一个绝对地址。它的值由汇编器来计算,它是 24 位有符号数,左移两位后有符号扩展为 32 位,表示的有效偏移为 26 位(+/- 32 M)。 
(2)ldr pc, =label
该指令是一条伪指令,将内存中的某个数据的位置(label处)赋给PC,同样依赖当前PC的值,但是偏移量是那个位置(label)的连接地址(运行时的地址),所以可以用它实现从Flash到RAM的程序跳转,说白了,pc是个地址数值。
伪指令LDR 常用于加载芯片外围功能部件的寄存器地址(32 位立即数),以实现各种
控制操作。
如:ldr    r0,=5e000000 ;将外围某IO端口寄存器的地址赋给r0,注意该立即数前面没有#。
---------------------------------------------------------------------------  
这里讲一下为什么会有ldr 伪指令 
   
范例demo.s:
arm汇编中的跳转指令
     .equ    STACK_BASE, 0x0c002000
arm汇编中的跳转指令
.equ    STACK_SIZE, 0x00001000
arm汇编中的跳转指令

.text
    ldr    sp, = STACK_BASE
    ldr    sl, = STACK_BASE - STACK_SIZE
    ldr    pc, = entry

这是一个合法的汇编文件,它把堆栈基址设为0x0c002000,栈限设为0x0c001000,然后跳到entry所标识的C程序中执行。

下面我们假设符号“entry”的地址为0x0c000000。

我们如果把上面代码写成:
    .text
    mov    sp, #0x0c002000
    mov    sl, #0x0c001000
    mov    pc, #0x0c000000
汇编器会报错:
demo.s: Assembler messages:
demo.s:2: Error: invalid constant -- `mov sp,#0x0c002000'
demo.s:3: Error: invalid constant -- `mov sl,#0x0c001000'  

    说起这个错误的原因可就话长了,简而言之是因为RISC有一个重要的概念就是所有指令等长。在ARM指令集中,所有指令长度为4字节(Thumb指令是2 字节)。那问题就来了,4字节是不可能同时存的下指令控制码和32位立即数的,那么我要把一个32位立即数(比如一个32位地址值)传送给寄存器该怎么 办?
    RISC CPU提供一个通用的方法就是把地址值作为数据而不是代码,从存储器中相应的位置读入到寄存器中。像在代码一中,将所有读取的32位数据放到label标 注的内存地址中,使用ldr伪指令,从该内存处读出该数据。因此label相当于一个内存地址。如下,给出了代码一的反汇编代码:让我们在Linux环境下执行下面的命令:
        arm-elf-as -o demo.o demo.s
        arm-elf-objdump -D demo.o

   结果:
    demo.o:     file format elf32-littlearm

Disassembly of section .text:

00000000 <.text>:
0:   e59fd004    ldr     sp, [pc, #4]    ; c <.text+0xc>
4:   e59fa004    ldr     sl, [pc, #4]    ; 10 <.text+0x10>
8:   e59ff004    ldr     pc, [pc, #4]    ; 14 <.text+0x14>
c:   0c002000    stceq   0, cr2, [r0]
10:  0c001000    stceq   0, cr1, [r0]
14:  00000000    andeq   r0, r0, r0
Disassembly of section .data:

    0、4、8三行相当于是代码段,C,10,14相当于是数据段,伪指令的变量定义存储在这里。由于entry还没连上目标地 址,objdump反汇编会认为是0,我们先不管它。另外两条LDR伪指令变成了实际的LDR指令!但目标很奇怪,都是[pc, #4]。那好我们看看[pc, #4]是什么。
    我们知道pc中存放的是当前指令的下下条指令的位置,也就是.+8。那么上面的第一条指令ldr sp, [pc, #4]中的pc就是0x8,pc+4就是0xc,而[0xc]的内容正是0x0c002000;同理,第二条ldr指令也是如此。显然这里LDR伪指令采用的是RISC通用的方法。
    另外从反汇编的代码可以看出ldr伪指令中存储的是一个相对偏移量,该偏移量是相对当前pc值的一个偏移量。  
------------------------------------------------------------------------------
(3)此外,有必要回味一下adr伪指令,U-boot中那段relocate代码就是通过adr实现当前程序是在RAM中还是flash中。
    ADR指令为小范围的地址读取伪指令.ADR指令将基于PC相对偏移的地址值读取到寄存器中.在汇编编译源程序时,ADR伪指令被编译器替换成一条合适的 指令.通常,编译器用一条ADD指令或SUB指令来实现该ADR伪指令的功能,若不能用一条指令实现,则产生错误,编译失败.
ADR 伪指令格式如下
        ADR{cond} register,exper  其中 
                    register 加载的目标寄存器
                    exper 地址表达式.当地址值是非字地齐时,取值范围-255~255 字节之间;当地址是字对齐时,取值范围-1020~1020 字节之间.对于基于PC 相对偏移的地址 值时,给定范围是相对当前指令地址后两个字处(因为ARM7TDMI 为三级流水线).
ADR 伪指令举例如下;
LOOP MOV R1,#0xF0

ADR R2,LOOP ;将LOOP 的地址放入R2
ADR R3,LOOP+4
可以用ADR 加载地址,实现查表:

ADR R0,DISP_TAB ;加载转换表地址
LDRB R1,[R0,R2] ;使用R2 作为参数,进行查表

DISP_TAB
DCB 0Xc0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,0x80,0x90

4 ldr pc,_label
  _label .word label
一般ldr pc,=label就被解释成上面这两条指令,但是从反汇编程序中可以看出由于偏移量仅为4k,_label的定义位置要和ldr指令相距在4k以内。借此可以实现大范围地址的跳转,完成从flash到sdram的跳转。
关键字:arm汇编  跳转指令 引用地址:arm汇编中的跳转指令

上一篇:LDR伪指令和LDR指令学习
下一篇:浅析arm汇编中^、、cxsf符号和movs等指令使用学习

推荐阅读最新更新时间:2024-03-16 14:53

ARM汇编快速入门
前言: 以前用ARM的IDE工具,使用的是ARM标准的汇编语言。现在要使用GNU的工具,当然要了解一点GNU ARM汇编的不同之处。其实非常的简单,浏览一下文档然后再看看程序就完全可以搞定了,或者你硬着头皮看GNU ARM的汇编程序,用不了多少时间你就就可以无师自通了。个人比较健忘,还是把文档翻译了一下,算是给自己一个避免遗忘的理由吧。 ARM汇编语言源程序语句,一般由指令,伪操作,宏指令和伪指令作成.ARM汇编语言的设计基础是汇编伪指令,汇编伪操作和宏指令. 目前常用的ARM编译环境有2种: ARMASM: ARM公司的IDE中使用了CodeWarrior的编译器,绝大多数windows下的开发者都在使用这一环境,完全按照
[单片机]
ARM汇编语言入门(四)
Part 4 内存指令:加载和存储 ARM使用加载(Load)/存储(Stroe)指令来读写内存,这意味着你只能使用LDR和STR指令访问内存。在ARM上数据必须从内存中加载到寄存器之后才能进行其他操作,而在x86上大部分指令都可以直接访问内存中的数据。如前所述,在ARM上增加内存里的一个32-bit数据值,需要三个指令(load,increment,store)。为了解释 ARM 上的 Load 和 Store 操作的基本原理,我们从一个基本示例开始,然后再使用三个基本偏移形式,每个偏移形式具有三种不同的寻址模式。为了简单化,每个示例,我们将在同一段汇编代码中使用不同 LDR/STR 偏移形式的。遵循这本段教程的最佳方法是在你的
[单片机]
<font color='red'>ARM汇编</font>语言入门(四)
ARM汇编指令的条件执行及其他相关细节
ARM指令在机器中的表示格式用32位的二进制数表示 例如 ADDEQS R0,R1,#8 表示为下表 31~28 27~25 24~21 20 19~16 15~12 11~0 0000 001 0100 1 0001 0000 000000001000 cond opcode Rn Rd
[单片机]
ARM汇编协处理器指令
协处理器(coprocessor),一种芯片,用于减轻系统微处理器的特定处理任务。 ARM 微处理器可支持多达 16 个协处理器用于各种协处理操作。 在程序执行的过程中,每个协处理器只执行针对自身的协处理指令,忽略 ARM 处理器和其他协处理器的指令。 ARM 的协处理器指令主要用于 ARM 处理器初始化 ARM 协处理器的数据处理操作,以及在ARM 处理器的寄存器和协处理器的寄存器之间传送数据,和在 ARM 协处理器的寄存器和存储器之间传送数据。   ARM协处理器包括以下5条:   CDP:协处理器数操作指令。   LDC:协处理器数据加载指令。   STC:协处理器存储指令。   MCR:ARM处理器寄存器到协
[单片机]
ARM汇编指令学习 实现数据块拷贝
这个学期,系里开了嵌入式的课程,正好借助这个机会系统地学习下ARM的指令系统。这个系列文章主要是通过一些简单的汇编程序实例来学习ARM指令,使用的编译器是ADS 1.2。 程序要求: 设计一段程序完成数据块的,数据从源数据区snum到目标数据区dnum,数据量大小为NUM字(1个字=4个字节),时以8个字为单位进行,对于最后所剩不到8个字的数据,以字为单位进行。 程序清单: 1 ;============================================================================== 2 ; blocks.s: 将数据从源数据区snum到目标数据区dnum,数据量大
[单片机]
<font color='red'>ARM汇编</font><font color='red'>指令</font>学习 实现数据块拷贝
浅析arm汇编指令使用学习
macro restore_user_regs ldr r1, ldr lr, ! @ !用来控制基址变址寻址的最终新地址是否进行回写操作, @ 执行ldr之后sp被回写成sp+#S_PC基址变址寻址的新地址 msr spsr,r1 @ 把cpsr的值保存到spsr中 ldmdb sp,{r0 - lr}^ @ lr= ,r13= ,r12= ,......,r0= @ 因为没对pc赋值,所以^的表示将数据恢复到User模式的 寄存器组中 mov r0,r0 add sp,sp,#S_FRAME_SIZE - S_PC movs pc,lr .endm 其
[单片机]
ARM汇编指令学习(1) 实现数据块拷贝
程序要求: 设计一段程序完成数据块的,数据从源数据区snum到目标数据区dnum,数据量大小为NUM字(1个字=4个字节),时以8个字为单位进行,对于最后所剩不到8个字的数据,以字为单位进行。 程序清单: 1 ;============================================================================== 2 ; blocks.s: 将数据从源数据区snum到目标数据区dnum,数据量大小为NUM字 3 ; 时以8个字为单位进行,最后不够8个字的数据按1个字为单位 4 ;=====================================
[单片机]
<font color='red'>ARM汇编</font><font color='red'>指令</font>学习(1) 实现数据块拷贝
ARM汇编中调用C函数的参数传递方式
对于ARM体系来说,不同语言撰写的函数之间相互调用(mix calls)遵循的是 ATPCS(ARM-Thumb Procedure Call Standard)标准,ATPCS主要是定义了函数呼叫时参数的传递规则以及如何从函数返回。 不同于x86的参数传递规则,ATPCS建议函数的形参不超过4个,如果形参个数少于或等于4,则形参由R0,R1,R2,R3四个寄存器进行传递;若形参个数大于4,大于4的部分必须通过堆栈进行传递。 我们先讨论一下形参个数为4的情况: 实例1 s// test_asm_args.asm //--------------------------------------------------------
[单片机]
小广播
添点儿料...
无论热点新闻、行业分析、技术干货……
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved