arm v8r中汇编伪指令.quad的详细用法
好的,我们来详细探讨一下在 ARMv8-R(AArch32 架构)的汇编语言中,GNU 汇编器(as)的伪指令 .quad 的用法。
1. .quad 是什么?
.quad 是 GNU 汇编器(as)提供的一个汇编伪指令。它的核心作用是:在当前的段(如 .data, .bss 或自定义段)中分配并初始化一个或多个 64 位(8 字节)的数据单元。
- 伪指令:它不像
MOV或ADD那样的 CPU 指令,不会被直接翻译成机器码。它的作用是指导汇编器如何在内存中布局数据。 - 字面意思:
quad来源于 "quadword",在 ARM 的上下文中,一个 "word" 是 32 位,因此一个 "quadword" 就是 4 * 32 = 128 位?这看起来有点矛盾。实际上,这是一个历史遗留的命名。在 GNU 汇编器中,.quad被明确定义为 8 字节(64 位),无论目标架构是 x86, ARM 还是其他。与之对应:.byte-> 1 字节 (8-bit).short/.hword-> 2 字节 (16-bit).word/.long-> 4 字节 (32-bit).quad-> 8 字节 (64-bit)
2. 语法格式
.quad expression[, expression ...]
- 你可以提供一个或多个表达式,多个表达式之间用逗号分隔。
- 每个表达式都会在内存中分配一个 64 位的空间,并用该表达式的值进行初始化。
- 表达式可以是:
- 数字常量(如
1234,0xABCD) - 标签/符号(如函数名、变量名,代表其地址)
- 复杂的数学表达式(如
_start + 4)
- 数字常量(如
3. 详细用法和示例
假设我们正在编写 ARMv8-R 的汇编代码,通常用于定义一些需要 64 位宽度的常量数据。
示例 1:定义数字常量
.data
/* 定义一个 64 位的整数 */
my_64bit_value: .quad 0x123456789ABCDEF0
/* 定义一组 64 位的值 */
some_constants: .quad 100, 0xFF, -1
my_64bit_value是一个标签,指向这块分配的内存地址。- 汇编器会在
.data段中分配 8 个字节,并按小端字节序将值0x123456789ABCDEF0存入。- 在内存中(小端序,低位字节在低地址):
my_64bit_value + 0:0xF0my_64bit_value + 1:0xDEmy_64bit_value + 2:0xBCmy_64bit_value + 3:0x9Amy_64bit_value + 4:0x78my_64bit_value + 5:0x56my_64bit_value + 6:0x34my_64bit_value + 7:0x12
- 在内存中(小端序,低位字节在低地址):
示例 2:定义地址(常用于 GOT、VDSO 等场景)
在系统编程中,经常需要存储函数或变量的地址。由于 ARMv8-R AArch32 的地址是 32 位的,直接用 .word 就够了。但如果你需要存储一个 64 位的值(例如,虽然不常见于 v8-R,但可能用于与 64 位模型交互或未来兼容),就可以用 .quad。
.text
.global _start
_start:
b main
/* 在数据段中存储一个 64 位的函数指针 */
function_pointer:
.quad _start /* 将 _start 的地址扩展为 64 位存储 */
.align 2
main:
/* 你的主程序代码 */
/* 例如,加载这个 64 位值到一对寄存器 (r1:r0) 中 */
ldr r0, =function_pointer
ldrd r0, r1, [r0] /* 从 function_pointer 指向的地址加载 8 字节到 R1(高32位)和 R0(低32位) */
...
重要提示:在纯粹的 32 位 ARMv8-R 环境中,地址是 32 位的。使用 .quad 存储一个 32 位地址时,高 32 位会被填充(通常是 0,或者由汇编器根据上下文决定)。你需要确保代码在处理这个 64 位值时能正确处理高 32 位。
示例 3:在特定段中分配(如 .bss)
.quad 也可以和 .skip 或 .space 伪指令一样,在未初始化的段(如 .bss)中分配空间,但语法稍有不同。通常更常见的做法是:
/* .bss 段用于未初始化的变量 */
.bss
/* 分配 8 字节未初始化空间,并用 my_buffer 标签标记其起始位置 */
my_buffer: .skip 8
/* 或者,使用 .comm 声明一个未初始化的通用符号 */
.comm large_number, 8, 8 /* 名称,大小(字节),对齐(字节) */
虽然可以直接在 .bss 段使用 .quad 0 来初始化为 0,但使用 .skip 或 .comm 意图更清晰。
4. 对齐问题
汇编器通常会为 .quad 数据保证自然对齐。对于 8 字节的数据,它通常会确保其地址是 8 字节对齐的。这是通过自动插入填充字节来实现的。
你也可以手动使用 .align 伪指令来确保对齐:
.data
.align 3 /* 2^3 = 8 字节对齐 */
important_64bit_data: .quad 0x1234567812345678
5. 与 ARM 自家汇编器(Armasm)的区别
请注意,.quad 是 GNU 汇编器的语法。如果你使用的是 ARM 自家的汇编器(如 Arm Compiler 中的 armasm),其伪指令完全不同。
- GNU Assembler (as):使用
.quad - ARM Assembler (armasm):使用
DCDO或DCQ(如果支持)DCDO用于分配 32 位数据,但其偏移量基于 RO 基址(与位置无关)。DCQ用于分配 64 位数据。
例如,在 Armasm 中等效的代码可能是:
AREA MyData, DATA, READWRITE
my_64bit_value DCD 0x9ABCDEF0, 0x12345678 ; 两个32位字组合成一个64位值
; 或者使用可能的 DCQ (需查阅特定工具链手册)
总结
| 特性 | 说明 |
|---|---|
| 伪指令 | .quad |
| 功能 | 在当前段中分配并初始化一个或多个 64 位(8 字节)的数据项。 |
| 语法 | .quad expression1[, expression2, ...] |
| 常用场景 | 定义 64 位整数常量、双精度浮点数字(如果架构支持该表示法)、64 位内存地址(在混合32/64位环境或特定场景下)。 |
| 对齐 | 汇编器通常会确保其按 8 字节边界自然对齐。 |
| 工具链 | GNU 汇编器 (as) 特有语法。ARM 自家工具链(Armasm)使用不同的指令(如 DCDO/DCQ)。 |
在 ARMv8-R 这种 32 位实时架构中,.quad 的使用频率可能不如 .word 高,但在需要处理 64 位数据时,它仍然是数据定义不可或缺的工具。使用时务必注意字节序和对齐问题。
浙公网安备 33010602011771号