【ARM64 常见汇编指令学习 13 -- ARM 汇编 ORG 伪指令学习】

文章目录

    • [ARM ORG 指令介绍](#ARM ORG 指令介绍)
      • [UEFI 中对 ORG 指令的使用](#UEFI 中对 ORG 指令的使用)

ARM ORG 指令介绍

在ARM汇编中,"org"是一个汇编器伪指令,用于设置下一条指令的装入地址。"org"后面跟着的是一个表达式,这个表达式的值就是下一条指令的装入地址。如果不用org规定则汇编得到的目标程序将从0x0000开始。两个org伪指令之间,除了指令代码,若有自由空间,则用0填充。

org 指令本身并不能决定程序将要加载到内存的什么位置 ,它只是告诉编译器,我的程序在编译好后需要加载到 xxx 地址,所以请你在链接时调整好数据访问时的地址,就是为程序中所有的引用地址增加一个段内偏移值

例如:

c 复制代码
.org 0x1000 
  mov r0, #10

上述代码中,".org 0x1000" 设置了下一条指令("mov r0, #10")的装入地址为0x1000。也就是说,当这个汇编文件被链接并加载到内存中时,"mov r0, #10"这条指令的地址将会是0x1000org 指令是链接时使用 的,不是汇编那一步使用的。即不是cpu的一条指令,而是给编译器看的伪指令。

另外,".org"通常只在裸机或者特殊的系统编程中使用,比如在写引导加载程序或者操作系统内核的时候。在普通的应用程序开发中,一般不需要使用".org",因为链接器和加载器会自动处理指令的装入地址。

UEFI 中对 ORG 指令的使用

我们可以在文件 ArmPkg/Include/Chipset/AArch64.h 中看到 org 指令的使用:

c 复制代码
#define VECTOR_ENTRY(tbl, off)    \
  .org off

#define VECTOR_END(tbl)           \
  .org 0x800;                     \
  .previous

从上面的实现可以看到 VECTOR_ENTRY 的作用是将其后面的内容放到 off 地址开始的地方,只需要关注其第2个参数。VECTRO_END的作用是将其后面的内容放到 0x800(2k)后。

我们知道 VECTRO_ENTRY 是在中断向量表中用到的宏,那我们先看下 ARMv8 UEFI 对于中断向量表是如何定义的呢?

见:edk2/ArmPkg/Library/ArmExceptionLib/AArch64/ExceptionSupport.S

ARMv8有4个异常级别,每一个异常级别对应一个 VBAR (Vector Base Address Register) 寄存器,用来指向异常向量表的基地址,每一个异常向量表的大小为128 个字节,也即可以存放32 条指令;同时每一个异常向量表会分为 4 组 ,每一组包含4 种异常

c 复制代码
//
// Current EL with SP0 : 0x0 - 0x180
//
VECTOR_ENTRY(ExceptionHandlersStart, ARM_VECTOR_CUR_SP0_SYNC)
ASM_PFX(SynchronousExceptionSP0):
  ExceptionEntry  EXCEPT_AARCH64_SYNCHRONOUS_EXCEPTIONS

VECTOR_ENTRY(ExceptionHandlersStart, ARM_VECTOR_CUR_SP0_IRQ)
ASM_PFX(IrqSP0):
  ExceptionEntry  EXCEPT_AARCH64_IRQ

VECTOR_ENTRY(ExceptionHandlersStart, ARM_VECTOR_CUR_SP0_FIQ)
ASM_PFX(FiqSP0):
  ExceptionEntry  EXCEPT_AARCH64_FIQ

VECTOR_ENTRY(ExceptionHandlersStart, ARM_VECTOR_CUR_SP0_SERR)
ASM_PFX(SErrorSP0):
  ExceptionEntry  EXCEPT_AARCH64_SERROR

//
// Current EL with SPx: 0x200 - 0x380
//
VECTOR_ENTRY(ExceptionHandlersStart, ARM_VECTOR_CUR_SPX_SYNC)
ASM_PFX(SynchronousExceptionSPx):
  ExceptionEntry  EXCEPT_AARCH64_SYNCHRONOUS_EXCEPTIONS, SP0

VECTOR_ENTRY(ExceptionHandlersStart, ARM_VECTOR_CUR_SPX_IRQ)
ASM_PFX(IrqSPx):
  ExceptionEntry  EXCEPT_AARCH64_IRQ

VECTOR_ENTRY(ExceptionHandlersStart, ARM_VECTOR_CUR_SPX_FIQ)
ASM_PFX(FiqSPx):
  ExceptionEntry  EXCEPT_AARCH64_FIQ

VECTOR_ENTRY(ExceptionHandlersStart, ARM_VECTOR_CUR_SPX_SERR)
ASM_PFX(SErrorSPx):
  ExceptionEntry  EXCEPT_AARCH64_SERROR
//
// Lower EL using AArch64 : 0x400 - 0x580
//
VECTOR_ENTRY(ExceptionHandlersStart, ARM_VECTOR_LOW_A64_SYNC)
ASM_PFX(SynchronousExceptionA64):
  ExceptionEntry  EXCEPT_AARCH64_SYNCHRONOUS_EXCEPTIONS

VECTOR_ENTRY(ExceptionHandlersStart, ARM_VECTOR_LOW_A64_IRQ)
ASM_PFX(IrqA64):
  ExceptionEntry  EXCEPT_AARCH64_IRQ

VECTOR_ENTRY(ExceptionHandlersStart, ARM_VECTOR_LOW_A64_FIQ)
ASM_PFX(FiqA64):
  ExceptionEntry  EXCEPT_AARCH64_FIQ

VECTOR_ENTRY(ExceptionHandlersStart, ARM_VECTOR_LOW_A64_SERR)
ASM_PFX(SErrorA64):
  ExceptionEntry  EXCEPT_AARCH64_SERROR

//
// Lower EL using AArch32 : 0x600 - 0x780
//
VECTOR_ENTRY(ExceptionHandlersStart, ARM_VECTOR_LOW_A32_SYNC)
ASM_PFX(SynchronousExceptionA32):
  ExceptionEntry  EXCEPT_AARCH64_SYNCHRONOUS_EXCEPTIONS

VECTOR_ENTRY(ExceptionHandlersStart, ARM_VECTOR_LOW_A32_IRQ)
ASM_PFX(IrqA32):
  ExceptionEntry  EXCEPT_AARCH64_IRQ

VECTOR_ENTRY(ExceptionHandlersStart, ARM_VECTOR_LOW_A32_FIQ)
ASM_PFX(FiqA32):
  ExceptionEntry  EXCEPT_AARCH64_FIQ

VECTOR_ENTRY(ExceptionHandlersStart, ARM_VECTOR_LOW_A32_SERR)
ASM_PFX(SErrorA32):
  ExceptionEntry  EXCEPT_AARCH64_SERROR

VECTOR_END(ExceptionHandlersStart)

上表中 VECTOR_ENTRY 第二个参数即为异常类型,对应的宏定义如下:

c 复制代码
// Vector table offset definitions
#define ARM_VECTOR_CUR_SP0_SYNC  0x000
#define ARM_VECTOR_CUR_SP0_IRQ   0x080
#define ARM_VECTOR_CUR_SP0_FIQ   0x100
#define ARM_VECTOR_CUR_SP0_SERR  0x180

#define ARM_VECTOR_CUR_SPX_SYNC  0x200
#define ARM_VECTOR_CUR_SPX_IRQ   0x280
#define ARM_VECTOR_CUR_SPX_FIQ   0x300
#define ARM_VECTOR_CUR_SPX_SERR  0x380

#define ARM_VECTOR_LOW_A64_SYNC  0x400
#define ARM_VECTOR_LOW_A64_IRQ   0x480
#define ARM_VECTOR_LOW_A64_FIQ   0x500
#define ARM_VECTOR_LOW_A64_SERR  0x580

#define ARM_VECTOR_LOW_A32_SYNC  0x600
#define ARM_VECTOR_LOW_A32_IRQ   0x680
#define ARM_VECTOR_LOW_A32_FIQ   0x700
#define ARM_VECTOR_LOW_A32_SERR  0x780

上面的宏定义正好和ARMv8 异常类型偏移对应一致:

上面只是配置中断类型的偏移底子,但是偏移地址是基于中断向量表的开始地址偏移的,那么中断向量表的开始地址在哪呢?

见:edk2/ArmPkg/Library/ArmExceptionLib/AArch64/ExceptionSupport.S

c 复制代码
//
// There are two methods for installing AArch64 exception vectors:
//  1. Install a copy of the vectors to a location specified by a PCD
//  2. Write VBAR directly, requiring that vectors have proper alignment (2K)
// The conditional below adjusts the alignment requirement based on which
// exception vector initialization method is used.
//

#if defined(ARM_RELOCATE_VECTORS)
GCC_ASM_EXPORT(ExceptionHandlersStart)
ASM_PFX(ExceptionHandlersStart):
#else
VECTOR_BASE(ExceptionHandlersStart)
#endif

这里我们主要看下 VECTOR_BASE

c 复制代码
#define VECTOR_BASE(tbl)          \
  .section .text.##tbl##,"ax";    \
  .align 11;                      \
  .org 0x0;                       \
  GCC_ASM_EXPORT(tbl);            \
  ASM_PFX(tbl):                   \

从上面可以看到 .org 0 也即中断向量表的地址在text 段 内偏移为 0 。那么实际的物理地址还需要看链接脚本是如何配置的。

相关推荐
Mephisto.java2 分钟前
【大数据学习 | kafka高级部分】kafka中的选举机制
大数据·学习·kafka
南宫生30 分钟前
贪心算法习题其三【力扣】【算法学习day.20】
java·数据结构·学习·算法·leetcode·贪心算法
武子康2 小时前
大数据-212 数据挖掘 机器学习理论 - 无监督学习算法 KMeans 基本原理 簇内误差平方和
大数据·人工智能·学习·算法·机器学习·数据挖掘
使者大牙2 小时前
【大语言模型学习笔记】第一篇:LLM大规模语言模型介绍
笔记·学习·语言模型
As977_2 小时前
前端学习Day12 CSS盒子的定位(相对定位篇“附练习”)
前端·css·学习
ajsbxi2 小时前
苍穹外卖学习记录
java·笔记·后端·学习·nginx·spring·servlet
Rattenking2 小时前
React 源码学习01 ---- React.Children.map 的实现与应用
javascript·学习·react.js
TeYiToKu3 小时前
笔记整理—linux驱动开发部分(9)framebuffer驱动框架
linux·c语言·arm开发·驱动开发·笔记·嵌入式硬件·arm
dsywws3 小时前
Linux学习笔记之时间日期和查找和解压缩指令
linux·笔记·学习
道法自然04023 小时前
Ethernet 系列(8)-- 基础学习::ARP
网络·学习·智能路由器