首页 > 解决方案 > 链接器在链接时是否生成绝对虚拟地址

问题描述

假设一个简单的 hello world in C,使用编译gcc -c到目标文件并使用objdump将如下所示进行反汇编:

_main:
       0:   55  pushq   %rbp
       1:   48 89 e5    movq    %rsp, %rbp
       4:   c7 45 fc 00 00 00 00    movl    $0, -4(%rbp)
       b:   c7 45 f8 05 00 00 00    movl    $5, -8(%rbp)
      12:   8b 05 00 00 00 00   movl    (%rip), %eax

如您所见,内存地址是0, 1, 4, ..等等。它们不是实际地址。

链接目标文件并反汇编它看起来像这样:

_main:
100000f90:  55  pushq   %rbp
100000f91:  48 89 e5    movq    %rsp, %rbp
100000f94:  c7 45 fc 00 00 00 00    movl    $0, -4(%rbp)
100000f9b:  c7 45 f8 05 00 00 00    movl    $5, -8(%rbp)
100000fa2:  8b 05 58 00 00 00   movl    88(%rip), %eax

我的问题是,100000f90虚拟内存字节的实际地址还是偏移量?

链接器如何在执行之前给出实际地址?如果执行时该内存地址不可用怎么办?如果我在另一台内存少得多的机器上执行它会怎样(可能在这里开始分页)。

分配实际地址不是装载机的工作吗?

链接器是否为他的最终可执行文件生成实际地址?

标签: macosassemblylinkerexecutablevirtual-memory

解决方案


(以下答案假设链接器没有创建与位置无关的可执行文件。)

我的问题是,100000f90 是虚拟内存字节的实际地址还是偏移量?

这是实际的虚拟地址。严格来说,它是与代码段基址的偏移量,但由于现代操作系统总是将代码段的基址设置为 0,因此它实际上是实际的虚拟地址。

链接器如何在执行之前给出实际地址?如果执行时该内存地址不可用怎么办?如果我在另一台内存少得多的机器上执行它会怎样(可能在这里开始分页)。

每个进程都有自己独立的虚拟地址空间。因为它是虚拟内存,所以机器中的物理内存量无关紧要。分页是虚拟地址映射到物理地址的过程。

分配实际地址不是装载机的工作吗?

是的,在创建进程时,操作系统加载程序会为进程分配物理页框,并将页面映射到进程的虚拟地址空间。但是虚拟地址是由链接器分配的。


推荐阅读