假设C
中的一个简单的hello世界,使用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
是虚拟内存字节的实际地址还是它的偏移量?
链接器如何在执行前提供实际地址?如果执行时该内存地址不可用怎么办?如果我在内存少得多的另一台机器上执行它(也许在这里启动分页)。
加载程序的工作是分配实际地址吗?
链接器是否为最终的可执行文件生成实际地址?
答案 0 :(得分:1)
(以下答案假定链接器未创建与位置无关的可执行文件。)
我的问题是,100000f90是虚拟内存字节的实际地址还是偏移量?
这是实际的虚拟地址。严格来说,它是距代码段基数的偏移量,但是由于现代操作系统始终将代码段基数设置为0,因此它实际上是实际的虚拟地址。
链接器如何在执行前提供实际地址?如果执行时该内存地址不可用怎么办?如果我在内存少得多的另一台机器上执行它(也许在这里启动分页)。
每个进程都有自己的单独虚拟地址空间。因为它是虚拟内存,所以计算机中的物理内存量无关紧要。分页是将虚拟地址映射到物理地址的过程。
加载程序的工作不是分配实际地址吗?
是的,在创建进程时,操作系统加载程序会为进程分配物理页面框架,并将页面映射到进程的虚拟地址空间。但是虚拟地址是链接器分配的地址。
答案 1 :(得分:-1)
链接器在链接时是否生成绝对虚拟地址
这取决于链接器设置和输入源。对于常规编程,链接器通常会努力创建位置无关的代码。
我的问题是,100000f90是虚拟内存字节的实际地址还是偏移量?
很可能是偏移量。
链接器如何在执行之前提供实际地址?
考虑操作系统的加载程序。它期望事物位于特定的地址位置。任何体面的链接器都将允许程序员以某种方式指定绝对地址。
如果执行时该内存地址不可用怎么办?如果我在内存少得多的另一台机器上执行它(也许在这里启动分页)。
这是位置相关代码的问题。
加载程序的工作是分配实际地址吗?
加载程序的工作是按照可执行文件中提供的说明进行操作。在创建可执行文件时,链接器可以在某些情况下指定地址或推迟到加载程序。