x64汇编器内存地址是4字节还是8字节?及列表文件地址解析
x64汇编器的内存地址长度与列表文件偏移解析
1. x64汇编器使用的内存地址长度
x64(AMD64/Intel 64)是64位架构,内存地址为8字节(64比特)。汇编器(比如你用的NASM)在处理x64代码时,会生成适配64位地址空间的目标文件(ELF64格式),但要明确两点:
- 汇编阶段(生成
.o文件),汇编器处理的是段内偏移或符号引用,还不是最终的虚拟内存地址,完整的64位虚拟地址要等到链接阶段(由gcc/ld链接器)确定; - 像
mov rsi, msg这类指令,汇编器会先把msg标记为.data段的符号,链接时再替换成该符号对应的64位虚拟地址。
2. NASM生成的hello.lst文件第二列地址含义
你通过nasm -f elf64 -g -F dwarf hello.asm -l hello.lst生成的列表文件,第二列的8位十六进制数是当前内容在所属段(section)内的偏移地址:
- 对于
.data段的msg,它的偏移是00000000,因为是.data段的第一个数据项; - 对于
.text段的代码,main标签的偏移是00000000,之后每条指令的偏移是累加指令字节长度得到的:比如mov rax, 1是5字节指令,下一条mov rdi,1的偏移就是00000005,以此类推; - 用8位十六进制显示是因为x64的段偏移最大可到64位(范围
0x0000000000000000到0xFFFFFFFFFFFFFFFF),NASM统一用8位十六进制格式输出,即使当前段内容偏移远小于这个范围,也会补零对齐,保持列表格式整齐。
对应你的代码,hello.lst的核心部分大概是这样:
1 ; hello.asm 2 00000000 section .data 3 00000000 68656C6C6F2C20776F726C64 msg db "hello, world",0 4 0000000D 00 5 section .bss 6 section .text 7 00000000 global main 8 00000000 main: 9 10 00000000 B801000000 mov rax, 1 ; 1 = write 11 00000005 BF01000000 mov rdi, 1 ; 1 = to stdout 12 0000000A 48BE[0000000000000000] mov rsi, msg ; string to display in rsi 13 00000014 BA0C000000 mov rdx, 12 ; length of the string, without 0 14 00000019 0F05 syscall ; display the string 15 0000001B B83C000000 mov rax, 60 ; 60 = exit 16 00000020 BF00000000 mov rdi, 0 ; 0 = success exit code 17 00000025 0F05 syscall ; quit
这里第二列的数值逻辑很清晰:
- 第3行的
00000000是msg在.data段的起始偏移; - 第10行的
00000000是main在.text段的起始偏移; - 第11行的
00000005是上一条5字节指令累加后的偏移结果。
当你用gcc链接生成可执行文件时,链接器会给每个段分配虚拟基址,比如.text段可能被加载到0x401000,那么main的实际虚拟地址就是0x401000 + 0x00000000 = 0x401000,mov rax,1这条指令的地址就是0x401000,以此类推。
内容的提问来源于stack exchange,提问作者Dzenis Zigo
相关产品推荐
相关产品推荐

