ARM指令浅析2(adrp、b) 您所在的位置:网站首页 adr和apr的区别 ARM指令浅析2(adrp、b)

ARM指令浅析2(adrp、b)

2023-08-21 07:25| 来源: 网络整理| 查看: 265

其实这篇文章的初衷是分析alpha架构下和arm架构下,为什么相同的用例arm生成的汇编指令会少一些,由于工作的保密性,暂时不介绍alpha生成的指令,因此先来主要分析一下,arm架构之所以少生成汇编指令的原因——adrp指令。

 

环境依然是ARM架构下的gcc编译器,编译选项为 -O2。

 

  4.Adrp指令

 

 

再来看一下arm编译器中的adrp指令

在了解adrp指令之前,首先要了解adr指令。以下是arm白皮书中对PC相关地址的计算描述——

 

 

 

ADR

 

作用:小范围的地址读取指令。ADR 指令将基于PC 相对偏移的地址值读取到寄存器中。

 

原理:将有符号的21位的偏移,加上PC, 结果写入到通用寄存器,可用来计算 +/- 1MB范围的任意字节的有效地址。

 

ADRP

 

 

 

 

作用:以页为单位的大范围的地址读取指令,这里的P就是page的意思。

 

原理:符号扩展一个21位的offset(immhi+immlo),  向左移动12位,PC的值的低12位清零,然后把这两者相加,结果写入到Xd寄存器,用来得到一块含有lable的4KB对齐内存区域的base地址(也就是说lable所在的地址,一定落在这个4KB的内存区域里,指令助记符里Page也就是这个意思), 可用来寻址 +/- 4GB的范围(2^33次幂)。

 

    通俗来讲,ADRP指令就是先进行PC+imm(偏移值)然后找到lable所在的一个4KB的页,然后取得label的基址,再进行偏移去寻址(结合下面的例子将会讲到)。

 

ADRP  {cond}  Rd  label

 

其中:Rd加载的目标寄存器。lable为地址表达式。

 

接下来进一步分析adrp的作用,首先写一个用例test3.c:

 

 

定义了四个全局变量,再分别赋值。test3.c生成的test.s如下:

 

 

 

在arm生成的.s中,在第一次由adrp取得页的基址(也就是lable)之后,省略了每次取变量地址的指令,而是在每次存储的过程中进行偏移。因此ARM生成的汇编汇总一共有11条指令。

 

其中adrp    x2, .LANCHOR0中,.LANCHOR0就是——一个大小为4KB的页的基址,而且在该页中,有第一个全局变量g的地址。Adrp指令的作用就是将该页的基址存到寄存器x2中。

 

然后,add指令会算出g的地址,x2+:lo12:  lo12是一个偏移量,这样就会得到g的地址,通过str指令将寄存器w3中的数据2存入到g的地址中。

 

接着根据g的地址x1进行偏移,由于是int型,所以每次都偏移4个字节,也就是看到的4、8、12,再将w2中的立即数分别存储到对应变量地址中。

 

 

 

再来看一下该用例的反汇编:

 

 

 

 

由反汇编我们可以看到,PC+imm(偏移值)得到了411000,这是一个大小为4KB的页中的一个基址(lable);且该页也是变量g所在的页。

 

具体分析如下:

 

1.      首先adrp指令计算出这个基址,然后将这个基址装入到寄存器x2中。

 

2.      Mov指令将立即数2装入到寄存器w3中。

 

3.      Add指令 计算出x2+0x28——x1的地址(也就是变量g所在的地址),偏移量为0x28。

 

4.      0x28就是十进制中的40,所以第四条str指令实际上是将立即数2(w3)装入到变量g(x1)所在的地址中。

 

5.      先取立即数到寄存器w2中,变量g的地址为x1,又因为是int型,所以偏移4位得到g2的基地址,再将w2中的值存储到x1+4的地址中。

 

6.      同理,g3,g4的赋值同样如此。

 

 

 

  5.b指令

 

依然以test1.c为例,加入打印printf。

 

 

当加入打印之后,arm处理器架构下gcc生成的汇编如下:

 

 

其中,b指令作用如下:

 

B

 

跳转指令。跳转到指定的地址执行程序。指令格式如下:

 

B  {cond}   label

 

这里是跳转至printf函数的地址执行pirntf函数。

 

它的反汇编如下:

 

 

 

 

 

 

由上面对adrp的分析可知,x0存放的是页的基地址,再由add指令进行偏移,得到另一个地址。

 

adrp    x0, 411000............................取得页的基址。

 

add     x0, x0, #0x30......................找到g的基址

 

mov     w1, #0x2............................将立即数装入到w1中

 

str     w1, [x0]..................................赋值给g

 

ldr     w1, [x0]..................................取数,w1寄存器作为打印的寄存器

 

adrp    x0, 400000 .................................再次找到一个页的基址

 

add     x0, x0, #0x6a8....................找到打印函数中字符串的地址

 

bl      400470 ...........................................带



【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有