伪指令 ADR 和 LDR

汇编中 adr 指令 和 ldr 指令的区别

首先看下面的例子:

.global _start
_start:
	ldr r0,=0x12345678  /* 将 无效立即数0x12345678 赋值寄存器r0 */
	ldr r1,=label       /* 将 标签所表示的地址值 赋值寄存器r1 */
	ldr r2,label        /* 将 标签所指地址处的内容 赋值寄存器r2 */
	adr r3,label        /* 将 标签所表示的地址值 赋值寄存器r3 */

stop:
	b stop
	
label:
	.word 0xdeadbeef

上面的代码在实际运行时,执行的是:

ldr-adr-disassembly

我们看到:

  1. 对于ldr r1,=labeladr r3,label,两条指令的功能都是获取标签所表示的地址值,但是编译器对两条伪指令的解释是不一样的。

对于指令ldr r1,=label,在编译的时候,根据链接地址,算出label标签对应的地址值(也就是说,其值是链接的时候决定的),将其放在文字池 (a portion of memory embedded in the code to hold constant values)中;运行时从文字池中取值,将值赋值给寄存器 r1。 Click here for more

对于指令adr r3,labeladr 是小范围地址加载指令,通过当前的PC的值 +/- 一个偏移量得到地址。很明显,这是一个位置有关码。标签必须位于当前代码段;应用超出范围的标签会出现错误 Click here for more。通常,编译器用一条 add 指令或 sub 指令来实现该 adr 伪指令的功能。所以,adr 指令得到的是运行时地址

  1. 编译器的对于伪指令ldr r0,=0x12345678的处理方式。将一个无效立即数通过文字池的方式赋值给寄存器。

  2. 由于流水线的缘故,PC的值总是指向正在预取的指令。

参考博客

如何确定代码的运行位置

/* 方法一 */
.global _start
_start:
	adr r0,_start
	ldr r1,=_start
	cmp r0,r1
/* 方法二 */
	adr r0,label
	ldr r1,[r0]
	cmp r0,r1
label:
	.word .
/* 方法三 Uboot 里的代码 */
	/* when we already run in ram, we don't need to relocate U-Boot.
	 * and actually, memory controller must be configured before U-Boot
	 * is running in ram.
	 */
	ldr	r0, =0xff000fff
	bic	r1, pc, r0       /* r1 <- current base addr of code */
	ldr	r2, _TEXT_BASE   /* r2 <- original base addr in ram */
	bic	r2, r2, r0       /* r2 <- current base addr of code */
	cmp r1, r2           /* compare r1, r2                  */
	beq after_copy       /* r1 == r2 then skip flash copy   */

_TEXT_BASE:
	.word text_base_addr /* text_base_addr 的值在链接脚本中确定 */

这是U-boot中的代码,比较当前PC值和 .text段基地址中的bit[12:23]是否相同。当前的PC值相对于.text段基地址已经运行了一段代码,但这段代码位于U-boot代码中比较靠前的位置,所以屏蔽了一些位,代码运行不会超过这个范围,可以通过这个比较得知当前代码是在iRAM中还是RAM中运行.

汇编中调用函数

方法一

ldr pc,label_one

label_one:
	.word lable_two
	
label_two:
	:
	:
	:

方法二

ldr pc,label_one

label_one:
	.word func_name /* define in C file */
void func_name(void)
{
    ...
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值