【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 。那么实际的物理地址还需要看链接脚本是如何配置的。

相关推荐
西岸行者6 天前
学习笔记:SKILLS 能帮助更好的vibe coding
笔记·学习
我在人间贩卖青春6 天前
汇编之伪指令
汇编·伪指令
悠哉悠哉愿意6 天前
【单片机学习笔记】串口、超声波、NE555的同时使用
笔记·单片机·学习
别催小唐敲代码6 天前
嵌入式学习路线
学习
毛小茛6 天前
计算机系统概论——校验码
学习
babe小鑫6 天前
大专经济信息管理专业学习数据分析的必要性
学习·数据挖掘·数据分析
winfreedoms6 天前
ROS2知识大白话
笔记·学习·ros2
在这habit之下6 天前
Linux Virtual Server(LVS)学习总结
linux·学习·lvs
我想我不够好。6 天前
2026.2.25监控学习
学习
im_AMBER6 天前
Leetcode 127 删除有序数组中的重复项 | 删除有序数组中的重复项 II
数据结构·学习·算法·leetcode