汇编代码地址何时确定?

文章摘要

汇编代码中的地址并非在编译阶段就固定,而是经过多阶段处理才最终确定。在编译阶段,变量和函数仅以符号名或相对偏移形式存在;汇编阶段将符号转换为目标文件的段内相对地址;链接阶段分配虚拟地址;最终在程序加载时,操作系统将虚拟地址映射到物理内存。整个过程表明,具体地址是在链接和加载阶段才确定的,而非编译期间。局部变量则始终通过寄存器偏移访问,没有绝对地址。


1. 汇编代码中的“地址”是什么?

  • 汇编代码(.s文件)中,变量、函数等通常以符号名(如mainfoovar)出现,或者以相对偏移(如4(%rbp))出现。
  • 只有极少数情况下(如绝对地址访问),才会出现具体的数值地址,但这通常是特殊用途。

2. 编译期间发生了什么?

  • 编译器(如gcc)将C代码翻译成汇编代码(.s文件),此时还没有具体的内存地址,只有符号和相对偏移。
  • 汇编器(如as)将汇编代码翻译成目标文件(.o),此时每个符号有一个相对地址(段内偏移),但还不是最终的内存地址。

3. 链接期间发生了什么?

  • 链接器(如ld)将多个.o文件和库文件合并成一个可执行文件(如ELF、PE等)。
  • 链接器会为每个段(.text、.data、.bss等)分配虚拟地址,并把符号解析为具体的段内偏移或虚拟地址。
  • 这时,可执行文件中的地址是虚拟地址,但还不是进程运行时的物理地址。

4. 加载期间发生了什么?

  • 当操作系统加载可执行文件时,会把各个段映射到进程的虚拟地址空间。
  • 这时,代码和数据的虚拟地址才最终确定,物理地址由操作系统的内存管理单元(MMU)动态分配。

5. 例子说明

5.1 源代码

int global_var = 42;

int main() {
    return global_var;
}

5.2 汇编代码(gcc -S)

    .globl  global_var
    .data
global_var:
    .long   42

    .globl  main
    .text
main:
    ...
    movl    global_var(%rip), %eax
    ...
  • 这里global_var是一个符号,没有具体地址

5.3 目标文件(.o)

  • global_var有一个段内偏移,比如.data段的第0个字节。

5.4 可执行文件

  • 链接器把.data段安排到虚拟地址0x601000(举例),那么global_var的虚拟地址就是0x601000。

5.5 运行时

  • 操作系统把0x601000映射到物理内存的某个位置,进程通过虚拟地址访问。

6. 局部变量的情况

  • 局部变量在栈上,汇编代码用%rbp%rsp等寄存器加偏移访问(如-4(%rbp)),没有绝对地址,只有相对偏移。

7. 总结

  • 编译期间,只有符号和相对偏移,没有最终的具体地址。
  • 链接期间,符号被分配到虚拟地址,但这只是可执行文件中的地址。
  • 加载期间,操作系统把虚拟地址映射到物理内存,进程通过虚拟地址访问。
  • 只有在程序运行时,地址才最终确定。

结论

汇编代码中的地址安排不是在编译期间就确定好具体地址的,而是在链接和加载阶段才最终确定。编译期间只有符号和相对偏移。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

你一身傲骨怎能输

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值