为什么0xfffffffc是要访问的无效地址?

时间:2018-10-11 06:31:39

标签: assembly cpu-architecture y86

您好,我正在读一本教科书,它说程序不允许访问更大的地址。 比0xc0000000(对于32位版本的Linux来说就是这样),因此以下汇编代码无效:

1. irmovl $1,%eax
2. xorl %esp,%esp // Set stack pointer to 0 and CC to 100
3. pushl %eax    // Attempt to write to 0xfffffffc, will fail

我很困惑。我有两个问题:

  1. 为什么不允许程序访问大于0xc0000000的地址,不是像0xc0000008这样的地址有效的地址?

  2. 如果确实不允许程序访问大于0xc0000000的地址,则0xfffffffc小于(小于)0xc0000000,那么为什么它会失败?

1 个答案:

答案 0 :(得分:5)

  
      
  1. 为什么不允许程序访问大于0xc0000000的地址,像0xc0000008这样的地址不是有效地址吗?
  2.   

现代操作系统利用硬件的功能来防止正在运行的应用程序相互干扰。这种隔离的主要组成部分是特权分离虚拟内存

虚拟内存(与物理内存相对)意味着代码访问的地址(例如mov指令)不是RAM的实际地址。相反,内存管理单元(MMU)利用页表转换虚拟地址(VA)转换为物理地址(PA),然后再发送虚拟地址到RAM。

特权分离是由CPU(和MMU)强制执行的,它使单个操作系统内核可以完全控制硬件,同时安全地运行多个用户。 em>应用。

将这两个概念放在一起,通常,内核在虚拟内存的一个区域(用户空间不可访问)中运行,而用户空间进程在另一部分中运行。

在Linux内核的x86 32位arch端口中,通常使用1-3拆分,以为内核提供1 GB的VA空间,为每个用户应用程序保留3 GB的VA空间。因此:

  • 0x00000000-0xBFFFFFFF:用户空间
  • 0xC0000000-0xFFFFFFFF:内核
  
      
  1. 如果真的不允许程序访问大于0xc0000000的地址,那么0xfffffffc小于(小于)0xc0000000,那么为什么它将失败?
  2.   

表示的方式(例如在硬件寄存器或内存中)与解释的方式(例如有符号/无符号整数,浮点数)之间存在很大差异数字,文本字符串,图片等)

请注意,如果将0xFFFFFFFF解释为32位二进制(带符号)整数,则得到-1。如果将其解释为无符号整数,则将得到(2 ^ 32-1)= 4294967295。

地址始终是无符号的;一般而言,当涉及到硬件时,不会有负数。

0xFFFFFFFC大于0xC0000000。因此,这是一个内核地址,任何尝试访问它的用户空间应用程序都会出错,并会传递SIGSEGV信号。