arm ldr/ld/数据加载系列指令和adr指令


ldrb指令

1. 语法

armv7手册语法:

LDRB{<c>}{<q>} <Rt>, [<Rn> {, #+/-<imm>}] Offset: index==TRUE, wback==FALSE
LDRB{<c>}{<q>} <Rt>, [<Rn>, #+/-<imm>]! Pre-indexed: index==TRUE, wback==TRUE
LDRB{<c>}{<q>} <Rt>, [<Rn>], #+/-<imm> Post-indexed: index==FALSE, wback==TRUE

<Rt> The destination register.
<Rn> The base register. The SP can be used. For PC use see LDRB (literal) on page A8-418.
+/- Is + or omitted if the immediate offset is to be added to the base register value (add == TRUE), or – if
it is to be subtracted (add == FALSE). #0 and #-0 generate different instructions.
<imm> The immediate offset used for forming the address. For the offset addressing syntax, <imm> can be
omitted, meaning an offset of 0. Any value in the range 0-4095 is permitted.

 功能描述:

Load Register Byte (immediate) calculates an address from a base register value and an immediate offset, loads a
byte from memory, zero-extends it to form a 32-bit word, and writes it to a register. It can use offset, post-indexed,
or pre-indexed addressing. For information about memory accesses see Memory accesses on page A8-291.

核心:从某个地址加载一个字节(Byte)到寄存器 Rt中,根据memory access方式不同分为:

  • Offset addressing
  • Pre-indexed addressing
  • Post-indexed addressing

2. Memory access mode

Offset addressing:

 Offset addressing:

The offset value is applied to an address obtained from the base register. The result is used as the address for the memory access. The value of the base register is unchanged. The assembly language syntax for this mode is:    [<Rn>, <offset>]

Pre-indexed addressing :

Pre-indexed addressing
The offset value is applied to an address obtained from the base register. The result is used as the address for the memory access, and written back into the base register. The assembly language syntax for this mode is: [<Rn>, <offset>]!

Post-indexed addressing :

Post-indexed addressing
The address obtained from the base register is used, unchanged, as the address for the memory access. The offset value is applied to the address, and written back into the base register The assembly language syntax for this mode is: [<Rn>], <offset>

3. 详细说明

  • Offset addressing:[Rn, offset]

        说明:最终访问内存的地址 = Rn+offset,这种操作后Rn的值不会改变

  • Pre-indexed addressing:[ Rn, offset] !

        说明:最终访问内存的地址 = Rn+offset,这种操作后Rn的值 = Rn+offset,注意加载的值来自地址:Rn + offset的值(更新后),类似于++i。       

  • Post-indexed addressing :[Rn],offset

        说明:最终访问内存的地址 = Rn,这种操作后Rn的值 = Rn+offset,跟pre-indexed的核心区别在于加载的值来自地址:Rn(更新前前),类似于i++

4. 实验验证:

通过实现一个c调用汇编的程序代码验证ldrb功能:

c程序:arm.c

#include<stdio.h>                                                                                                                                          
#include<string.h>
#include<stdlib.h>

extern void asm_strcpy(const char *src, char *dest);

int main(){
    const char *s = "Hello World";
    char tmp[32];
    memset(tmp, 0, sizeof(tmp)/sizeof(char));
    asm_strcpy(s, tmp);
    printf("-----%s------\n", tmp);
}
~  

汇编程序:ldrb.S

.globl asm_strcpy                                                                                                                                          
asm_strcpy:
loop:
    ldrb    r4, [r0, #1]!
    cmp     r4,#0
    beq     over
    strb    r4,[r1], #1
    b       loop

over:
    mov     pc,lr

.type asm_strcpy,%function

编译:arm-linux-androideabi-gcc -o ldrb ldrb.S arm.c  -pie -fPIE 

运行:

D:\tmp>adb shell ldrb
-----ello World------

可以看到由于采用了[r0, #1] pre-indexed的memory access方式,r4寄存器加载的值来自于地址:r0 + 1。如果改成ldrb r4, [r0], #1,可正常输出Hello Wold,如下:

D:\tmp>adb shell ldrb
-----Hello World------

ldr指令

1.语法

Load Register (immediate) calculates an address from a base register value and an immediate offset, loads a word
from memory, and writes it to a register. It can use offset, post-indexed, or pre-indexed addressing. For information
about memory accesses see Memory accesses on page A8-291.

于ldrb的区别在于一次加载一个word长度的数据。arm32位中即32 bit的数据。

举例:

1. ldr     r0, =0x00000001    @加载立即数1到寄存器r0,= 意思对变量取地址

2. 
.globl get_int
get_int:
    ldr     r0, =abc        @将0x10数值加载r0寄存器
    mov     pc,lr

.long       abc                                                                                                                                            
.equ        abc, 0x10

1)LDR R0,[R1,R2,LSL #2]!

将存储器地址为R1+R2*4的字数据读入到寄存器R0中,并将新地址R1+R2*4写入R1

2)LDR R0, [R1, R2, LSL #2]

将存储器地址为R1+R2*4的字数据读入到寄存器R0中。

ldrex指令

Load Register Exclusive calculates an address from a base register value and an immediate offset, loads a word from
memory, writes it to a register and:
• if the address has the Shared Memory attribute, marks the physical address as exclusive access for the
executing processor in a global monitor
• causes the executing processor to indicate an active exclusive access in the local monitor.

ldrex跟ldr核心区别实现原子操作,如内核的atomic_cmpxchg就是基于ldrex和strex指令实现,具体可以参考如下文章:

宋宝华:关于ARM Linux原子操作的实现_linux阅码场的技术博客_51CTO博客

 LDR伪指令

用于加载一个32位立即数或地址值到寄存器,【有点像MOV,但不是访存】!!!
语法:LDR{condition} register,=[expression | label-expression]

.global _start
_start:
    //list地址存入r0寄存器,注意这就不是pic了
	ldr r0, =list	
	ldr r1, [r0]
	
.data
list:
	.word 1,2,3

LDMIA

格式:

LDM{<c>}{<q>} <Rn>{!}, <registers>

说明:

Load Multiple Increment After (Load Multiple Full Descending) loads multiple registers from consecutive memory locations using an address from a base register. The consecutive memory locations start at this address, and the address just above the highest of those locations can optionally be written back to the base register. The registers loaded can include the PC, causing a branch to a loaded address.

根据官方文档描述LDMIA是LD = Load, M:Multiple, I : Increment A; “!”代表Rn寄存器会随着数据加载而增加。IA类似c语言的i++,即先加载完第一个数据到寄存器列表,再执行“r0++”。

举例:

.global _start
_start:
	ldr r0, =list	
	ldr r1, [r0]
	
    //r0存储list地址
	adr r0, list
    //从r0寄存器指向的开始加载,r2 = 1, r3 =2
	ldmia r0!, {r2, r3}

list:
	.word 1,2,3
	

LDMIB

理解了LDMIA,LIDMIB就简单了,B代表Before,解Increment Before,类似c语言的++i,具体到该指令就是先把Rn寄存器地址增加,然后在加载,即“++Rn",还是用上面代码举例:

.global _start
_start:
	ldr r0, =list	
	ldr r1, [r0]
	
	adr r0, list
    //r2 = 2, r3 = 3,因为先将r0寄存地址增加了,即所谓的Increment Before (load)
	ldmib r0!, {r2, r3}

list:
	.word 1,2,3

有IB/IA,同样也有DB/BA(Decrement),意义就很好理解了,不再代码举例。

ADR指令

参考:ADR (PC-relative)----获取同节中标号所代表的内存地址_ASMARM的博客-CSDN博客

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值