LDR伪指令和LDR指令学习

来源:互联网 发布:601519历史交易数据 编辑:程序博客网 时间:2024/03/28 15:51

全文摘自:http://www.linuxso.com/linuxrumen/16306.html

ARM是RISC结构,数据从内存到CPU之间的移动只能通过L/S指令来完成,也就是ldr/str指令。比如想把数据从内存中某处读取到寄存器中,只能使用ldr比如:

ldr r0, 0x12345678
就是把0x12345678这个地址中的值存放到r0中。而mov不能实现这个功能,mov只能在寄存器之间移动数据,或者把立即数移动到寄存器中,这个和x86这种CISC架构的芯片区别最大的地方。x86中没有ldr这种指令,因为x86的mov指令可以将数据从内存中移动到寄存器中。
 另外还有一个就是ldr伪指令,虽然ldr伪指令和ARM的ldr指令很像,但是作用不太一样。ldr伪指令可以在立即数前加上=,以表示把一个值(一般是一个地址)写到某寄存器中,比如:
ldr r0, =0x12345678

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

其实ldr指令可以装载一个32bit立即数的说法并不确切,因为实际上并不是这一条语句装载了一个32bit立即数,真正的汇编代码是将某个地址的值传递给r1,就是说需要一个地址存放0x12345678这个立即数。而且如果这个立即数可以用mov指令的形式来表达,会被编译器实际用mov来代替比如:

ldr r1,=0x10
会变成
mov r1,#0x10 

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

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

实例:

/*来自u-boot-2010.06\arch\arm\arm920t\start.s  158行--162行*/# if defined(CONFIG_S3C2410)    ldr    r1, =0x3ff    ldr    r0, =INTSUBMSK    str    r1, [r0]# endif
/*来自u-boot-2010.06\arch\arm\arm920t\start.s  180行--189行*/
relocate:                /* relocate U-Boot to RAM        */
    adr    r0, _start        /* r0 <- current position of code   */
    ldr    r1, _TEXT_BASE        /* test if we run from flash or RAM */
    cmp    r0, r1            /* don't reloc during debug         */
    beq    stack_setup

    ldr    r2, _armboot_start
    ldr    r3, _bss_start
    sub    r2, r3, r2        /* r2 <- size of armboot            */
   add    r2, r0, r2        /* r2 <- source end address         */