如何在NASM的text段初始化结构体值并解决对应编译报错
问题解决说明
报错原因及修复方案
1. symbol 'test_struc.value' undefined报错
NASM的struc语法中,结构体成员本质是相对于结构体首地址的偏移常量,不属于实例的附属符号,不支持实例名.成员名的寻址格式。正确写法是用结构体实例地址+成员偏移名的组合,将原代码里的mov rax, [test_struc.value]修改为mov rax, [test_struc + value]即可解决。
注意:加中括号是取成员对应内存的内容,不加中括号是取成员的地址,请根据你的实际需求选择。
2. label '_exit' changed during code generation报错
这是NASM的前向引用导致的问题:你在_start里引用_exit标签时,标签还未被定义,NASM默认会将其识别为32位近地址,后续定义标签时判定地址长度不匹配就会抛出错误。两种修复方式选其一即可:
- 把
_exit标签的定义移到_start之前 - 引用时明确指定跳转类型,写成
jmp near _exit
原需求适配说明
你最初需要不在rodata段初始化结构体、可直接写入结构体值的要求,现在把结构体实例放在.data段已经完全满足:.data是可读写数据段,不属于只读的rodata段,运行时可以直接修改test_struc内的数值。
如果你非要把结构体定义在代码段(.text),需要注意默认.text是只读段,直接写入会触发段错误,链接时给ld加上--omagic参数即可将.text段改为可写权限,正常写入数据。
修复后的完整代码
BITS 64 global _start ; 结构体定义统一放在段声明前,仅定义结构布局不占实际存储空间 struc test value: resb 256 endstruc segment .bss segment .data name db "Bryton", 0 test_struc: istruc test at value, db "Hello world" iend segment .text ; 提前定义_exit标签解决前向引用问题 _exit: mov rax, 0x3c mov rdi, 0 syscall _start: mov rax, [test_struc + value] mov rax, name jmp _exit
编译链接命令参考:nasm -f elf64 struct.s -o struct.old struct.o -o struct
内容的提问来源于stack exchange,提问作者Bryton
相关产品推荐
相关产品推荐

