精华内容
下载资源
问答
  • LDR指令的形式是“LDR Rn,=expr”,例: COUNT EQU 0x40003100 …… LDR R1,=COUNT MOV R0,#0 STR R0,[R1] COUNT是我们定义的一个变量,地址为0x40003100。这种定义方法在汇编语言中是很常见的。 LDR R1...
    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指令和一条 DCD伪指令。
     
     
    ARM指令LDR和ARM伪指令LDR有什么区别
    伪指令LDR{cond} register, ={expr|label-expr}
    expr为32为常量。编译器根据expr的取值情况来处理这条伪指令:
    1、当expr表示的地址没有超过mov或mvn指令中地址的取值范围时,编译器用合适的mov指令或mvn指令代替该LDR伪指令。
    2、当expr表示的地址超过了mov或mvn指令中地址的取值范围时,编译器将该常数放在缓冲区中,同时用一条基于PC的LDR指令读取该常数。
    由于arm是risc精简指令集,指令都是32位的,在编码中操作码,目标和源寄存器是要占掉32位一部分,
    所以一条指令里面不可能存一个32位的立即数,所以arm提供了一条伪指令来完成一条指令load一个32位的立即数。
    方法是在这条指令附近放要load的值,再利用当前的pc+偏移load这个数,注意ldr的原来的意义是将内存的某个值load到寄存器里面。
    比如:
    ldr r0, =0x5000010
    经过arm的assembler的翻译实际上就是:
    ldr r0, [pc+#0x4] ;;指令是4byte 32位,就是将内存中下一个word放到r0中
    0x500010 ;;这个地方放的是数值。这里,0x4是在它立即数的范围内的
     
    arm指令中mov和ldr的区别
    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伪指令和ldr指令不是一个同东西。
     

    ARM伪指令之地址读取:ADR ADRL LDR
    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指令从文字池读出常量。
    展开全文
  • 指令ldr补充

    2019-07-14 02:15:50
    上一篇文章说到ldr,adr区别,在这补充一下实验结果 汇编源码如下 _start: .word 1 .word 2 .word 3 .word 4 ldr pc, main ldr pc, =main adr pc, main led_blink: ldr r1, =0xE0200244 mov...

    上一篇文章说到ldr,adr区别,在这补充一下实验结果

    汇编源码如下

    _start:
    	.word 1
    	.word 2
    	.word 3
    	.word 4
    	ldr pc, main
    	ldr pc, =main					
    	adr pc, main
    
    led_blink:
    	ldr r1, =0xE0200244 					
    	mov r0, #0
    	str r0, [r1]
    
    	bl delay							
    
    	ldr r1, =0xE0200244 					
    	mov r0, #0x38
    	str r0, [r1]
    
    	bl delay	
    
    	sub r2, r2, #1
    	cmp r2,#0
    	bne led_blink
    main:
    	bl delay
    
    
    delay:
    	mov r0, #0x900000
    delay_loop:
    	cmp r0, #0
    	sub r0, r0, #1
    	bne delay_loop
    	mov pc, lr
    

    经过编译、链接、反编译后得到对应反汇编文件如下

    start.elf:     file format elf32-littlearm
    
    
    Disassembly of section .text:
    
    00000000 <_start>:
       0:	00000001 	andeq	r0, r0, r1
       4:	00000002 	andeq	r0, r0, r2
       8:	00000003 	andeq	r0, r0, r3
       c:	00000004 	andeq	r0, r0, r4
      10:	e59ff030 	ldr	pc, [pc, #48]	; 48 <main>
      14:	e59ff044 	ldr	pc, [pc, #68]	; 60 <delay_loop+0x10>
      18:	e28ff028 	add	pc, pc, #40	; 0x28
    
    0000001c <led_blink>:
      1c:	e59f1040 	ldr	r1, [pc, #64]	; 64 <delay_loop+0x14>
      20:	e3a00000 	mov	r0, #0
      24:	e5810000 	str	r0, [r1]
      28:	eb000007 	bl	4c <delay>
      2c:	e59f1030 	ldr	r1, [pc, #48]	; 64 <delay_loop+0x14>
      30:	e3a00038 	mov	r0, #56	; 0x38
      34:	e5810000 	str	r0, [r1]
      38:	eb000003 	bl	4c <delay>
      3c:	e2422001 	sub	r2, r2, #1
      40:	e3520000 	cmp	r2, #0
      44:	1afffff4 	bne	1c <led_blink>
    
    00000048 <main>:
      48:	ebffffff 	bl	4c <delay>
    
    0000004c <delay>:
      4c:	e3a00609 	mov	r0, #9437184	; 0x900000
    
    00000050 <delay_loop>:
      50:	e3500000 	cmp	r0, #0
      54:	e2400001 	sub	r0, r0, #1
      58:	1afffffc 	bne	50 <delay_loop>
      5c:	e1a0f00e 	mov	pc, lr
      60:	00000048 	andeq	r0, r0, r8, asr #32
      64:	e0200244 	eor	r0, r0, r4, asr #4
      68:	00001a41 	andeq	r1, r0, r1, asr #20
      6c:	61656100 	cmnvs	r5, r0, lsl #2
      70:	01006962 	tsteq	r0, r2, ror #18
      74:	00000010 	andeq	r0, r0, r0, lsl r0
      78:	45543505 	ldrbmi	r3, [r4, #-1285]	; 0x505
      7c:	08040600 	stmdaeq	r4, {r9, sl}
      80:	Address 0x00000080 is out of bounds.
    

    可以看出_start标号的函数中三条指令被编译器转换,ldr指令就是直接写一个常数到寄存器。而adr则是根据当前pc寄存器值进行计算,再跳转。

     

    后记:

    实验过程中遇见不少问题记录一下。

    arm-linux-objdump

    -i  显示支持的目标文件格式和CPU架构

    -f file  查看file文件的整体头部摘要信息

    #arm-linux-objdump -f start.bin 

    start.bin:     file format elf32-littlearm
    architecture: arm, flags 0x00000112:
    EXEC_P, HAS_SYMS, D_PAGED
    start address 0x00000000

    实验流程:

    arm-linux-gcc -c -o start.o start.S
    arm-linux-ld -Tlink.lds  -o start.elf start.o
    arm-linux-objcopy -O binary start.elf start.bin
    arm-linux-objdump -D start.elf > start_elf.dis

    过程编译源文件得到.o文件--->链接得到.elf文件----->转换为二进制.bin文件

    通过.elf文件反汇编得到反汇编文件。

    ELF与BIN文件区别:

    Gcc 编译出来的是ELF文件。通常gcc –o test test.c,生成的test文件就是ELF格式的,在linuxshell下输入./test就可以执行。

    Bin 文件是经过压缩的可执行文件,去掉ELF格式的东西。是直接的内存映像的表示。在系统没有加载操作系统的时候可以执行。

    elf(executable  and   link   format)文件里面包含了符号表,汇编等。
    BIN文件是将elf文件中的代码段,数据段,还有一些自定义的段抽取出来做成的一个内存的镜像。

    展开全文
  • ARM指令 LDR r,=imd

    2011-01-18 19:17:00
    ARM指令 LDR 和 ADR的一些区别 收藏 LDR 是ARM中的指令,也是伪指令。 当用 LDR r, =imd // r 为寄存器, imd为立即数 LDR 是一条伪指令。编译器会根据 立即数的大小,决定用 ldr 指令或者是...

    ARM指令 LDR 和 ADR的一些区别 收藏
    LDR 是ARM中的指令,也是伪指令。

    当用 LDR r, =imd  // r 为寄存器, imd为立即数

    LDR 是一条伪指令。编译器会根据 立即数的大小,决定用 ldr 指令或者是mov或mvn指令。

    当imd能用mov或者mvn操作时,就将它翻译成一条mov或mvn指令。当imd大于mov或mvn能够操作的数时,编译器会将imd存在一个内存单元中,然后再用一条ldr指令加载这个内存单元的的值到寄存器中。

    LDR r, label  和 LDR r, =label的区别:

    LDR r, =label 会把label表示的值加载到寄存器中,而LDR r, label会把label当做地址,把label指向的地址中的值加载到寄存器中。

    譬如 label的值是 0x8000, LDR r, =label会将 0x8000加载到寄存器中,而LDR r, label则会将内存0x8000处的值加载到寄存器中。

    ADR 和 ADRL 伪指令:

    ADR 和 ADRL 伪指令用于将一个地址加载到寄存器中。

    ADR为小范围的地址读取伪指令。ADR指令将基于PC相对偏移的地址值读取到寄存器中。在汇编编译源程序时,ADR伪指令被编译器替换在一条合适的指令,通常,编译器用一条ADD指令或SUB指令来实现该ADR伪指令的功能,若不能使用一条指令实现,则产生错误。其能加载的地址范围,当为字节对齐时,是-1020~1020,当为非字对齐时在-255~255之间。

    ADRL是中等范围的地址读取指令。会被编译器翻译成两条指令。如果不能用两条指令表示,则产生错误。

    ADRL能加载的地址范围当为非字节对齐时是-64K~64K之间;当为字节对齐时是-256K~256K之间。


    本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/wojiwoye/archive/2010/05/01/5547998.aspx

    展开全文
  • ARM指令ldr和adr的区别

    2020-12-14 08:40:01
    很多人在写简单的裸机代码或分析uboot时,常常遇到adr ldr指令。却分不清这2者的区别,今天就来谈谈adr与ldr指令。 先写启动代码test_adr.S: .text .globl _start _start: ldr r0, test adr r0, test ldr r0, =...

    很多人在写简单的裸机代码或分析uboot时,常常遇到adr ldr指令。却分不清这2者的区别,今天就来谈谈adr与ldr指令。

    先写启动代码test_adr.S:

    .text
    .globl _start
    _start:
        ldr r0, test
        adr r0, test
        ldr r0, =test
        nop
    test:
        nop
    

    Makefile:

    all:test_adr.S
           arm-linux-gcc -c -o test_adr.o test_adr.S
             arm-linux-ld -Ttext 0x00000000 -gtest_adr.o -o test_adr_elf
            arm-linux-objcopy -O binary -S test_adr_elf test_adr.bin
            arm-linux-objdump -D -m arm test_adr_elf test_adr.dis
    clean:
            rm -ftest_adr.dis test_adr.bin test_adr_elf *.o
    

    反汇编test_adr.S得到test_adr.dis:

    test_adr_elf:
    file format elf32-littlearm
    Disassembly of section .text:
    00000000 _start:
    0: e59f0008 ldr r0, [pc, #8]; 10 test
    4: e28f0004 add r0, pc, #4; 0x4
    8: e59f0004 ldr r0, [pc, #4]; 14.text+0x14
    c: e1a00000 nop (mov r0,r0)
    00000010 test:
    10:e1a00000 nop (mov r0,r0)
    14:00000010 andeq r0, r0, r0, lsl r0
    

    很显然,ldr获取的是内存的值(至于这个内存存的是数据还是地址,不是问题重点),像指针一样间接寻址(看到了[]符号咯),而adr是得到一个与PC有关的值,必定是个地址。

    adr r0, _start,r0就是_start对应指令当前的地址
    对于“_start对应指令当前的地址”,我理解了很久,终于想清楚,比如在uboot中,_start标号对应的指令(即b reset)的链接地址是0x33f80000确凿无疑。

    如果从NOR Flash启动,b reset被烧在NOR Flash 0地址,那么b reset相对于此时的PC来说,它的地址就是0。

    如果u-boot被直接下载到SDRAM的0x33f80000处运行,那么b reset自然处在SDRAM的0x33f80000。

    所谓“当前”—是以运行时的PC为参照。

    下面基于以上理解,分析test_adr.dis

    00000000 _start:
    0: e59f0008 ldr r0, [pc, #8]; 10 test
    4: e28f0004 add r0, pc, #4; 0x4
    8: e59f0004 ldr r0, [pc, #4]; 14.text+0x14
    c: e1a00000 nop (mov r0,r0)
    
    00000010 test:
    10:e1a00000 nop (mov r0,r0)
    14:00000010 andeq r0, r0, r0, lsl r0
    

    1、先分析第一条指令ldr r0,test被编译成ldr
    r0, [pc, #8],即到当前PC+8的存储器取值,运行第一条指令时,PC其实已经是8了(流水线决定的)。

    那么8+8等于0x10,所以r0等于e1a00000,此指令的作用就是读取test地址处存放的值。由于此处放了一条nop,即得到nop的机器码。

    2、第二条adr r0,test被编译成add r0, pc, #4
    这显然是依赖程序执行到此处的PC值。ADR是小范围地址读取伪指令,会将基于PC 相对偏移的地址值读取到寄存器中,此指令在4地址,PC是4+8=0xc再加4,于是r0=0x10。

    从结果上来看,test自身的值(标号值),被读到了r0,这个值是以PC为参考的,也就是test对应的指令(第二个nop)当前的地址。r0=(标号test的地址与此指令的距离差)+(此指令的地址)=((0x10-0x4=12)+(4))=16=0x10。

    假如在0x30000000以上运行,r0=((12)+(0x30000004))= 0x30000010。

    3、ldr r0,=test被编译成两个字,一个指令,一个文字池。执行到这里PC=8, 8+8+4=0x14,所以在14地址取值,编译器在14地址处放了0x00000010,0x00000010是test的值,假如在Makefile指定连接地址是0x30000000,那么编译器放在这里的就是0x30000010,可见,这个值是编译时确定的。

    最后一行andeq r0, r0, r0, lsl r0大概是编译器的机械动作,把一个数字翻译成了指令。

    总结

    ADR是小范围的地址读取伪指令,它将基于PC 相对偏移的地址值读取到寄存器中。而ldr获取的是内存的值,像指针一样间接寻址。

    展开全文
  • 汇编指令ldr str stm ldm

    2020-08-16 15:39:37
    ldr命令:把数据从内存加载到寄存器 ldr r0, =addr ;r0 = addr ldr r1, [r0] ; r1 = *r0 ldr r1, [r0, #4] ; r1 = *(r0+4) ldr r1, [r0, #4] ! ; r1 = *(r0+4);r0=r0+4; ldr r1, [r0], #4 ; r1 = *(r0);r0=r0+4; ...
  • LDR伪指令LDR数据传送指令的区别

    千次阅读 2010-05-07 21:27:00
    ARM指令集中,LDR通常都是作加载指令的,但是它也可以作伪指令LDR指令的形式是“LDR Rn,=expr”。下面举一个例子来说明它的用法。 COUNT EQU 0x40003100……LDR R1,=COUNTMOV R0,#0STR R0,[R1]COUNT是我们...
  • 关于汇编指令ldr和str的理解

    千次阅读 2018-03-16 22:01:23
    (1)..ldr指令:(load装载) 外存---&gt;&gt;&gt;内存 ldr 指令传数据(将数据传入寄存器) 无论是否是立即数,都可以进行传 格式:ldr 寄存器,=数字 若数字式立即数:ldr 指令(ldr 寄存器,=数字)和 ...
  • ARM指令 LDRLDR指令、MOV的区别

    千次阅读 2012-03-12 19:02:50
    ARM体系中,数据从内存到CPU寄存器之间移动只能使用LDR/STR(此处LDR不是伪指令),MOV只用于寄存器之间移动数据或者把有限制的立即数赋给寄存器。例如下面的语句:  COUNT EQU 0x40003100  LDR R1,=COUNT  ...
  • ARM伪指令LDR&ADR的作用相同,都是讲标号所代表的地址赋予寄存器,但是二者的实现机制是不一样的: LDR采用绝对地址,ADR采用相对地址。从而也导致其结果可能会不一样,也因此可以用来搭配使用,实现代码的重定位。...
  • arm汇编指令ldr用法总结

    万次阅读 2016-01-02 12:03:20
    一、ldr的两种用法:  1、 ldr pc, =label . 即把label后的数据或者指令的运行地址赋值为pc。运行地址 = 链接地址 + 这些数据或指令相对于程序起始...二、以u-boot中lowlevel_init函数的一段代码说明ldr指令的用法。
  • ARM是RISC结构,数据从RAM到CPU寄存器之间的移动只能通过L/S指令来完成,也就是ldr/str指令。   比如想把数据从RAM中某处读取到CPU寄存器中,只能使用ldr 比如: ldr r0, 0x12345678 就是把0x12345678这个地址...
  • 每条arm指令都会操作寄存器,寄存器就类似于c语言中的变量,r0~12通用寄存器 1:mov指令 mov r0,#100 //r0=100  常量整数只有12位来存储 mov r0,r1 //r0=r1 mvn r0,#100 //r0=~100 mvn r0,r1 //r0=~r1   2...
  • 在ARM汇编指令中,ldr是一条常用的内存访问指令,如: ldr r1, [r2] //将地址为r2的内存单元位数据读取到r1中 它也可以作为大范围的地址读取伪指令,如: ldr r1, =label //r1=label的地址 label: …… 这里...
  • ARM是RISC结构,数据从RAM到CPU寄存器之间的移动只能通过L/S指令来完成,也就是ldr/str指令。 比如想把数据从RAM中某处读取到CPU寄存器中,只能使用ldr 比如: ldr r0, 0x12345678 就是把0x12345678这个地址中的...
  • 文件名:start.S 1 .globl _start 2 3 _start: ...4 ldr r0, =0x11111111 5 6 b . 7 反汇编文件名:start_elf.dis 1 start.elf: file format elf32-littlearm 2 3 4 Disasse...
  • LDR 是ARM中的指令,也是伪指令。 当用 LDR r, =imd // r 为寄存器, imd为立即数 LDR 是一条伪指令。编译器会根据 立即数的大小,决定用 ldr 指令或者是mov或mvn指令。 当imd能用mov或者mvn操作时,就将它翻译成...
  • ldr,str,ldm,stm的命名规律: 这几个指令命名看起来不易记住,现在找找规律。 指令 样本 效果 归纳名称解释 ldr Rd,addressing ldr r1,[r0] addressing to Rd [mem to reg] load to register ...
  • arm 的伪指令ldr的作用

    2014-04-16 05:04:20
    求教,请问ldr,r0,=(__global_offset_table_ - 0x84Ce)的含义是什么?我的理解和我预期的答案不一样,新人很困惑,global这时取的是地址还是地址的内容,0x84ce又怎么解释?,,,这句代码的作用说是可以定位到got...
  • 2、MOV指令 MOV指令可以把立即数或者寄存器内容(注意:这里绝对不可以是内存!!)传递给一个寄存器。   MOV对于立即数是有要求的,就是上边的“8位图”数据。 只能由一个8bit连续有效位通过偶数次移位得到的...
  • 指令LDR和ADR的分析

    千次阅读 2010-08-29 19:22:00
    在ARM汇编程序中,就经常使用到LDR和ADR这两条伪指令,现在对这两条伪指令进行分析,欢迎大家指正。  在资料中,ADR的定义为:小范围的地址读取伪指令,ADR指令将基于PC相对偏移的地址值读取到寄存器中...
  • 1、LDR LD=LoaD(加载) R=Register(寄存器) ;STR ST=STore(存储)R=Register(寄存器) https://zhidao.baidu.com/question/381927727.html 2,MRS Move Register Special
  • 指令LDR R0, =0xf454f00

    千次阅读 2009-12-25 09:45:00
    LDR R1, =0x12345678 LDR R0, =LED_TAB 如果这些数值不太复杂,那么就会用mov指令代替,比如: ldr r1, =0x00 在编译时就会变成: mov r1, #0x00 如果这些数值很复杂,那么编译时,这个数值会被保

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 1,373
精华内容 549
关键字:

指令ldr