x86 - C是否使用虚拟或线性地址?

时间:2014-05-20 10:38:26

标签: c assembly x86 memory-address

假设您处于x86保护模式,因此启用了分段。

考虑以下代码:

// main
int stackvar, *ptr;

// ptr may contain the address of a variable located in the stack segment
ptr = &stackvar;

// ptr may contain the address of a variable in the heap (data segment)
ptr = (int *) malloc(sizeof(int));

我已经读过ptr只包含偏移量(即虚拟地址),并且不包含段的指示。这意味着它应该与段基地址组合以获得线性地址。这是真的吗?

// let %eax = ptr
asm("movl (%eax), %ebx"); // which segment is used by this instruction?

如果%eax仅包含偏移量而不包含段的指示,那么机器如何知道应该应用哪个段基地址(例如数据或堆栈段基址)?

2 个答案:

答案 0 :(得分:3)

如果未使用显式段覆盖,则会有许多操作码附加隐式段 - 请参阅汇编程序手册。

答案 1 :(得分:1)

您已经混淆了两个不同的概念:偏移量与虚拟地址。

除非您是操作系统(或设备驱动程序),否则受保护模式OS中的每个进程都会获得自己的地址空间。当我这样说时,我并不是说他们获得了分配给他们的~4gig地址空间的一部分。我的意思是x86中的每个进程都拥有它自己的~4gig地址空间。

在这种环境中,完全可能同时运行的两个完全不相关的应用程序都可以调用malloc,并且两者都返回相同的地址。但这并不意味着它们指向相同的数据。来自process1的地址0x804a008与进程2的地址0x804a008无任何关联。

当进程尝试访问该地址时,处理器内部会发生魔法(请参阅TLBs)以启用进程' "地址"进入物理内存位置,导致每个进程读取完全不同的内存。这不是你在汇编转储中看到的东西。只要受保护模式应用程序访问内存,处理器就会执行此操作。

因此每个进程都有自己的线性地址空间,而ptr确实指向了地址位置。当你说" ptr只包含偏移量(即虚拟地址)"这不正确。它包含虚拟地址,句点。它没有抵消任何东西。

回到16bit的黑暗时代,确实存在分段寻址的概念。更重要的是,处理所有直接访问的物理内存并且倾向于相互踩踏。除非我误解了你的问题或你的(未指明的)平台,否则这根本不会影响那个malloc。

对于那里的kibitzers,是的,我正在简化。人们可以(并且已经)写过关于这些东西的全书。