PC 与负载或 link 地址有什么关系?

what does PC have to do with load or link address?

Link地址是程序执行的地址,而加载地址是程序实际放置在内存中的地址。

现在我很困惑程序计数器的值是多少?是加载地址还是link地址?

两者是不同的概念,在不同的上下文中使用。 Linker/Loader主要负责代码搬迁和修改; PC是一个数字计数器,指示程序序列的位置(不是类型的address/location,如linker/loader)。

Linking & Loading :-

The heart of a linker or loader's actions is relocation and code modification. When a compiler or assembler generates an object file, it generates the code using the unrelocated addresses of code and data defined within the file, and usually zeros for code and data defined elsewhere. As part of the linking process, the linker modifies the object code to reflect the actual addresses assigned. For example, consider this snippet of x86 code that moves the contents of variable a to variable b using the eax register.

mov a,%eax 
mov %eax,b

If a is defined in the same file at location 1234 hex and b is imported from somewhere else, the generated object code will be:

A1 34 12 00 00 mov a,%eax 
A3 00 00 00 00 mov %eax,b

Each instruction contains a one-byte operation code followed by a four-byte address. The first instruction has a reference to 1234 (byte reversed, since the x86 uses a right to left byte order) and the second a reference to zero since the location of b is unknown.

Now assume that the linker links this code so that the section in which a is located is relocated by hex 10000 bytes, and b turns out to be at hex 9A12. The linker modifies the code to be:

 A1 34 12 01 00 mov a,%eax  
 A3 12 9A 00 00 mov %eax,b

That is, it adds 10000 to the address in the first instruction so now it refers to a's relocated address which is 11234, and it patches in the address for b. These adjustments affect instructions, but any pointers in the data part of an object file have to be adjusted as well.


Program Counter :-

The program counter (PC) is a processor register that indicates where a computer is in its program sequence.

In a typical central processing unit (CPU), the PC is a digital counter (which is the origin of the term "program counter") that may be one of many registers in the CPU hardware. The instruction cycle begins with a fetch, in which the CPU places the value of the PC on the address bus to send it to the memory.

The memory responds by sending the contents of that memory location on the data bus. (This is the stored-program computer model, in which executable instructions are stored alongside ordinary data in memory, and handled identically by it).

Following the fetch, the CPU proceeds to execution, taking some action based on the memory contents that it obtained. At some point in this cycle, the PC will be modified so that the next instruction executed is a different one (typically, incremented so that the next instruction is the one starting at the memory address immediately following the last memory location of the current instruction).

Link address is the address where execution of a program takes place

不,不是。

while load address is the address in memory where the program is actually placed.

有点。程序通常由多个指令组成,所以不能放在一个"load address".

当人们谈论加载地址时,他们通常谈论的是 可重定位 可以重定位(在运行时)到任意加载地址的代码。

例如,让我们以地址 0x20020 链接的程序为例,该程序由 100 条 4 字节指令组成,所有指令均按顺序执行(例如,它是一个 ADD 序列,后跟一个 SYSCALL 退出程序)。

如果在地址 0x20020 加载这样的程序,那么在运行时程序计数器的值为 0x20020,然后它将前进到 0x20024 处的下一条指令,然后到 0x20028,等等,直到到达程序的最后一条指令 0x201ac

但是如果该程序在地址 0x80020020 加载(即如果程序从其链接地址被 0x80000000 重定位),则程序计数器将从 0x80020020,最后一条指令将在 0x800201ac.

请注意,在许多操作系统上,可执行文件不可重定位,因此必须 始终 加载到它们链接的相同地址(即重定位 0;在这种情况 "link address" 确实是执行开始的地址),而共享库几乎总是可重定位的,并且通常链接在地址 0 并且具有非零重定位。

我会把 "load address" 这个词从你的想法中剔除。它并不真正存在于现代操作系统中。在过去,多个程序加载到同一地址 space(并且每个程序都加载到连续的内存区域),加载地址具有重要意义。现在它没有。他就是为什么。

一个可执行文件通常会定义许多不同的程序段。这些可能不会连续加载到内存中。例如,链接器通常会指示创建远离程序其他区域的堆栈区域。

可执行文件将指示应该是 PC 初始值的位置。这可能不在程序段的开头,更不用说在第一个程序段中了。