如果我写一条指令x = 7,我将x理解为某个地址。然后,什么为x分配一个内存地址?这个地址是虚拟地址,然后转换为物理内存地址吗?
答案 0 :(得分:0)
如果我写一条指令x = 7,我将x理解为某个地址。然后,什么为x分配一个内存地址?
这取决于var x
的类型。
如果x
是全局或静态变量,则有几种工具将配合使用以为其指定地址
x
的全局变量所需的文件。 x
将位于@data_segment+0x1000
。然后,链接器将通过x
@data_segment+0x1000
的所有引用。
@data_segment
的值和x
1 的实际地址。如果x
是局部变量,则情况会稍微简单一些。所有局部变量都在堆栈中,并且其地址是由编译器相对于堆栈(或帧)指针计算的。因此x
的地址将类似于@stack_pointer+8
,它是由编译器生成的。但是它的实际值只有在执行时才知道,并且取决于堆栈指针。
如果x
是动态分配的(malloc-ed),则仅在运行时知道其地址。 malloc()
向操作系统请求内存块,并在其中动态定位vars。 x
的位置将取决于malloc()
此地址是虚拟地址,然后转换为物理内存地址吗?
计算机看到的所有地址都是虚拟地址,它们会转换为物理内存地址。
1 程序段(包括数据段)的虚拟地址过去对于程序的不同执行是恒定的,但现在不再适用。出于安全原因,它们是randomized。
答案 1 :(得分:0)
通常有四种方法可以完成此操作。
1)变量被映射到硬件寄存器。在这种情况下,x没有地址。
2)变量具有绝对地址。通常认为这是错误的形式,因为使用绝对地址的代码无法重定位。意味着必须将其放置在地址空间中的固定位置。但是,在某些情况下,变量必须位于特定的位置,例如设备的某些接口。
在这种情况下,x的地址可以由编译器或链接器指定。
3)将该变量定义为与堆栈相关的寄存器的偏移量。是大多数编程语言中用于实现局部变量的方法。如果您有4个字节的整数,并说一个C声明,如
int x,y;
在没有其他变量的函数中,该函数的顶部有类似以下内容的指令:
SUBL2 #8, SP ; Allocate 8 bytes from the stack
MOVL SP, BP ; Set the Base Pointer Register to the start of the allocation
其中SP是堆栈指针,而BP是一些基于指针的寄存器。
在这种情况下,x可能是位于BP + 0处的偏移量,y可能是在BP + 4处的偏移量。
因此类似
x = y
看起来像
MOVL X(BP),Y(BP)
或写为:
MOVL(BP),4(BP)
x和y的存储位置在运行时完全确定。只有相对于基本指针寄存器的偏移量是已知的。实际上,如果递归地或通过中断调用包含它们的函数,则可能同时存在多个具有不同地址的x和y。
4)存储器位置是另一个寄存器偏移量(通常是程序计数器)。
假设您使用的是传统的大写FORTRAN,其中所有变量都是静态的。编译器通常会确定变量的位置,但使用程序计数器寄存器(或某些其他寄存器)的偏移量来引用它。变量在运行时保留在固定位置,但是位置可以是可变的。使用这样的偏移量可使代码独立于位置。表示可以将其加载到内存中的任何位置。这样一来,代码便可以在可以由多个程序使用的共享库中使用。
通常,编译器会为变量设置一些位置,然后由链接程序修复。