zoukankan      html  css  js  c++  java
  • 汇编--LDR

    转载:https://my.oschina.net/zengsai/blog/23733

    ARM LDR 伪指令的格式:

    LDR     Rn, =expr

    如果name是立即数的话
    LDR R0,=0X123;//将0X123存入R0
    如果name时个标识符
    LDR R0,=NAME;//将NAME的地址存入R0

    LDR    R0, =0x3FF5000  ; 伪指令: 把 0x3FF5000 直接赋值给 R0,相当于 R0=0x3FF5000。
    LDR    R0, 0x3FF5000   ; 存储访问指令: 把以 0x3FF5000 为地址的存储单元中的数据赋值给 R0, 相当于 R0=[0x3FF5000]。

    附1 《ARM中LDR伪指令与LDR加载指令》:

    ARM指令集中,LDR通常都是作加载指令的,但是它也可以作伪指令。

    ARM是RISC结构,数据从内存到CPU之间的移动只能通过L/S指令来完成,也就是ldr/str指令。

    比如想把数据从内存中某处读取到寄存器中,只能使用ldr 加载指令
    比如:
    ldr r0, 0x12345678 
    就是把0x12345678这个地址中的值存放到r0中。

    而mov不能干这个活,mov只能在寄存器之间移动数据,或者把立即数移动到寄存器中,这个和x86这种CISC架构的芯片区别最大的地方。
    x86中没有ldr这种指令,因为x86的mov指令可以将数据从内存中移动到寄存器中。

    虽然ldr伪指令和ARM的ldr指令很像,但是作用不太一样。ldr伪指令可以在立即数前加上=,以表示把一个地址写到某寄存器中,比如:
    ldr r0, =0x12345678

    这样,就把0x12345678这个地址写到r0中了。所以,ldr伪指令和mov是比较相似的。只不过mov指令限制了立即数的长度为8位,也就是不能超过512。而ldr伪指令没有这个限制。如果使用ldr伪指令时,后面跟的立即数没有超过8位,那么在实际汇编的时候该ldr伪指令是被转换为 mov指令的。

    ldr伪指令和ldr指令不是一个同东西。


    附2 《ARM 伪指令之地址读取 》

    1、ADR伪指令--- 小范围的地址读取 

         ADR伪指令将基于PC相对偏移的地址值或基于寄存器相对偏移的地址值读取到寄存器中。在汇编编译器编译源程序时,ADR伪指令被编译器替换成一条合适的指令。通常,编译器用一条ADD指令或SUB指令来实现该ADR伪指令的功能,若不能用一条指令实现,则产生错误,编译失败。

    ADR伪指令格式 :ADR{cond}   register, expr

    地址表达式expr的取值范围:

        当地址值是字节对齐时,其取指范围为: +255  ~ 255B;

        当地址值是字对齐时,其取指范围为:   -1020 ~ 1020B;

    2、ADRL伪指令----中等范围的地址读取

    ADRL伪指令将基于PC相对偏移的地址值或基于寄存器相对偏移的地址值读取到寄存器中,比ADR伪指令可以读取更大范围的地址。在汇编编译器编译源程序时,ADRL伪指令被编译器替换成两条合适的指令。若不能用两条指令实现,则产生错误,编译失败。

    ADRL伪指令格式:ADRL{cond}   register, expr

    地址表达式expr的取值范围:

        当地址值是字节对齐时,其取指范围为: -64K~64K;

        当地址值是字对齐时,其取指范围为:   -256K~256K;

    3、LDR伪指令-----大范围的地址读取

    LDR伪指令用于加载32位的立即数或一个地址值到指定寄存器。在汇编编译源程序时,LDR伪指令被编译器替换成一条合适的指令。若加载的常数未超出MOV或MVN的范围,则使用MOV或MVN指令代替该LDR伪指令,否则汇编器将常量放入文字池,并使用一条程序相对偏移的LDR指令从文字池读出常量。

    转载:https://www.cnblogs.com/hnrainll/archive/2011/06/14/2080241.html

    ARM指令集中,LDR通常都是作加载指令的,但是它也可以作伪指令。

    LDR伪指令的形式是“LDR Rn,=expr”。下面举一个例子来说明它的用法。

    COUNT EQU       0x40003100

    ……

    LDR       R1,=COUNT

    MOV      R0,#0

    STR       R0,[R1]

    COUNT是我们定义的一个变量,地址为0x40003100。这中定义方法在汇编语言中是很常见的,如果使用过单片机的话,应该都熟悉这种用法。

    LDR       R1,=COUNT是将COUNT这个变量的地址,也就是0x40003100放到R1中。

    MOV      R0,#0是将立即数0放到R0中。最后一句STR      R0,[R1]是一个典型的存储指令,将R0中的值放到以R1中的值为地址的存储单元去。实际就是将0放到地址为0x40003100的存储单元中去。可 见这三条指令是为了完成对变量COUNT赋值。用三条指令来完成对一个变量的赋值,看起来有点不太舒服。这可能跟ARM的采用RISC有关。

    下面还有一个例子

    ;将COUNT的值赋给R0

    LDR       R1,=COUNT

    LDR       R0,[R1]

    LDR       R1,=COUNT这条伪指令,是怎样完成将COUNT的地址赋给R1,有兴趣的可以看它编译后的结果。这条指令实际上会编译成一条LDR指令和一条DCD伪指令。

    LDR 的两种用法
    1)LDR pc, =MyHandleIRQ 表示将MyHandleIRQ符号放入pc寄存器中
    2)LDR PC,MyHandleIRQ 表示将读取存储器中MyHandleIRQ符号所表示的地址中的值,及需要多读一次存储器。
     
    在代码中:
    start:
            ldr pc,=MyHandleReset   @jump to HandleReset
            ldr pc,=MyHandleUndef   @jump to HandleUndef
            ldr pc,=MyHandleSWI     @jump to HandleSWI
            ldr pc,=MyHandleIabort  @jump to HandleIabort
            ldr pc,=MyHandleDabort  @jump to HandleDabort
            nop
            ldr pc,=MyHandleIRQ     @jump to HandleIRQ             <=之前出错的一行
            ldr pc,=MyHandleFIQ     @jump to HandleFIQ
     
    @MyHandleIRQ:   .word OS_CPU_IRQ_ISR
    MyHandleIRQ:
            sub lr, lr, #4          @ to calculate the return address      
            stmdb sp!, {r0-r12,lr}
            ldr lr, =int_return     @ restore the return address
            ldr pc, =int_handle     @ call for the interrupt handler
    在“之前出错的一行”处,如果改成“ldr pc,MyHandleIRQ”当中断来临时,无法进行中断处理。
     
    另一种情况是正确的,注意体会:
    start:
            ldr pc,=MyHandleReset   @jump to HandleReset
            ldr pc,=MyHandleUndef   @jump to HandleUndef
            ldr pc,=MyHandleSWI     @jump to HandleSWI
            ldr pc,=MyHandleIabort  @jump to HandleIabort
            ldr pc,=MyHandleDabort  @jump to HandleDabort
            nop
            ldr pc,MyHandleIRQ     @jump to HandleIRQ             <=之前出错的一行
            ldr pc,=MyHandleFIQ     @jump to HandleFIQ
     
    MyHandleIRQ:   .word OS_CPU_IRQ_ISR
    @MyHandleIRQ:
    @        sub lr, lr, #4          @ to calculate the return address      
    @        stmdb sp!, {r0-r12,lr}
    @        ldr lr, =int_return     @ restore the return address
    @        ldr pc, =int_handle     @ call for the interrupt handler
    因为当中断来临时,还需要去MyHandleIRQ处把OS_CPU_IRQ_ISR取出,即多取一次存储器。
  • 相关阅读:
    跨平台GUIQt windows 开发环境安装配置(Eclipse CDT+ MinGW+QT) (转载)
    跨平台GUIQt windows 开发环境安装配置(VS2005+QT+IntegrationPlugin)(转载)
    跨平台GUIQt ACER Aspire on Linux 开发环境安装配置(QT + GCC ) (原创)
    移动视频监控(2)原型开发Symbian客户端进展。
    编程语言大串联(1)C#,Java,C++
    优化页面上的sql
    一个段错误调试
    查询数据库空间
    shell 批量替换多个文件中字符串
    用户组相关
  • 原文地址:https://www.cnblogs.com/zhiminyu/p/13994694.html
Copyright © 2011-2022 走看看