zoukankan      html  css  js  c++  java
  • C语言中使用的地址是真实的物理地址吗?

    设置程序基址固定:关闭程序基地址改变

    在vs中编写代码如下:

    #include <stdio.h>

    int main()
    {
    int a = 5;
    printf("a的内存地址是 %d", &a);
    system("pause");
    return 0;
    }

    编译生成程序,找到vs生成的Test.exe文件,我们双击运行Test.exe,发现变量a的内存地址是1703668,

    然后不关闭这个程序,再双击运行Test.exe,发现又运行起来一个程序,显示a的内存地址是1703668。

    如图:

    很奇怪啊,第一次运行时申请的变量a的内存地址是1703668,再次运行Test.exe时,内存地址1703668不是已经被占用了吗,为什么第二个程序的变量a的内存地址还是1703668?

    这说明C语言中,或者说所有的编程语言中使用的内存地址都不是真实的物理地址,而是虚拟地址。

    虚拟地址:CPU启动保护模式后,程序运行在虚拟地址空间中。

    PS:不是所有程序都运行在虚拟地址中。CPU启动时是运行在实模式下的,Bootloader以及内核在初始化页表之前并不使用虚拟地址,而是直接使用物理地址的。

    如果CPU寄存器中的分页标志位被设置,那么执行内存操作的机器指令时,CPU(准确来说,是MMU,即Memory Management Unit,内存管理单元)会自动根据页目录和页表中的信息,把虚拟地址转换成物理地址,完成该指令。
    比如 mov eax,[004227b8h] ,这是把地址004227b8h处的值赋给寄存器的汇编代码,004227b8这个地址就是虚拟址。CPU在执行这行代码时,发现寄存器中的分页标志位已经被设定,就自动完成虚拟地址到物理地址的转换,使用物理地址取出值,完成指令。对于Intel CPU 来说,分页标志位是寄存器CR0的第31位,为1表示使用分页,为0表示不使用分页。对于初始化之后的 Win2k 我们观察 CR0 ,发现第31位为1。表明Win2k是使用分页的。
     
    由此可知,虽然我们每次运行Test.exe得到的a的内存地址都是一样的,但我们知道这是虚拟地址,每次运行时申请到的物理内存的地址肯定是不一样的。
     
    更多虚拟地址的问题参考:https://baike.baidu.com/item/%E8%99%9A%E6%8B%9F%E5%9C%B0%E5%9D%80/1329947?fr=aladdin
  • 相关阅读:
    BZOJ 3924: [Zjoi2015]幻想乡战略游戏
    codevs 4244 平衡树练习
    BZOJ 2002: [Hnoi2010]Bounce 弹飞绵羊
    BZOJ 2038: [2009国家集训队]小Z的袜子
    luogu P3709 大爷的字符串题
    BZOJ 2120: 数颜色
    luogu P2056 采花
    luogu P2709 小B的询问
    BZOJ 1878: [SDOI2009]HH的项链
    Codeforces 221d D. Little Elephant and Array
  • 原文地址:https://www.cnblogs.com/fengxing999/p/10209835.html
Copyright © 2011-2022 走看看