GAS汇编宏中如何正确引用.data数据段的数据值?
核心原因
GAS(GNU汇编器)的宏是预处理阶段的纯文本替换机制,宏展开的执行时机远早于段数据解析、符号寻址、指令编码流程,根本不会解析传入参数对应的符号地址、内存存储内容——你传什么文本,宏就原封不动把这段文本替换到宏体的对应位置。
你写的宏里.string "\str"的逻辑,是直接把传入的str参数的文本内容拼接成字符串,所以调用newcat test时,宏展开后等价于直接写.string "test",完全不会去读取test标签下存储的"abc"内容。哪怕你传(test)、$test这类寻址写法,宏拿到的也只是对应的文本字符串,会把括号、美元符号都当成普通字符存到字符串里,不会做任何寻址求值。
对应解决方式
根据实际需求二选一即可:
- 如果你需要生成一份独立的字符串副本:调用宏时直接传入字符串字面量,不要传标签名,同时调整宏体的字符串定义写法,不需要额外加引号转义:
.macro newcat str newcat: .ascii \str .equ newcat_len, .-newcat .endm .section .data # 直接传入带引号的字符串字面量 newcat "abc"
- 如果你只是要复用已经在.data段定义好的
test字符串,不需要额外复制副本:不要在宏里重新定义字符串内容,直接做符号映射即可,还能节省内存:
.macro newcat str_label newcat = \str_label .equ newcat_len, . - \str_label .endm .section .data test: .string "abc" # 传入已定义的字符串标签,直接复用其地址和长度 newcat test
第二种写法完全适配你后续的write系统调用逻辑,newcat会直接指向存"abc"的内存地址,newcat_len计算的就是"abc"的长度,运行时可以正常打印出预期内容。
宏仅做文本替换,不具备解析符号对应存储内容的能力,不要尝试给宏传标签来获取标签指向的内存数据,这类需要求值、寻址的逻辑都要等宏展开完成后,才会进入后续的汇编流程处理。
内容的提问来源于stack exchange,提问作者OnlyWick
相关产品推荐
相关产品推荐

