虚拟地址

Published: by Creative Commons Licence

看了《操作系统真象还原》中关于虚拟地址的部分,故此做一下笔记,以做备忘。

页表项及页目录项

   virtual_dir_table

  • 第0位:Present,表示是否在内存中,1表示在内存中,0表示不在内存中
  • 第1位:RW,读写位,1表示可读可写,0表示只可读
  • 第2位:普通用户/超级用户位,1表示普通用户(0,1,2,3特权级均可访问),0表示超级用户(仅0,1,2特权级可访问)(这里的特权级既保护模式下的特权级)
  • 第3位:PWT,页级通写位,1表示使用write-through缓冲策略,0表示使用Write-back缓冲策略
  • 第4位:PCD,页级高速缓存禁止位,1表示页或页表不可以被缓冲,0表示页或页表可以被缓冲
  • 第5位:Accessed,访问位,1表示该页被CPU访问过,0表示还未被CPU访问
  • 第6位:Dirty,1表示CPU对该页执行过写操作,主要是在换出内存时有用
  • 第7位:PAT,页属性表位,直接置0(作用尚未明确)。
  • 第8位:Global,1表示全局页,该页在高速缓存TLB中一直保存,0表示非全局页

虚拟地址到物理地址的转化([]表示取地址):
页表基地址 = [(页目录项基地址 + (虚拟地址 » 22) * 4)] & 0xfffff000
物理地址 = [(页表基地址 + (虚拟地址 » 12 & 0x3ff) * 4)] & 0xfffff000 + 虚拟地址 & 0xfff

   virtual_to_physical

进入虚拟地址

首先获取物理地址大小
可以用int 0x15中断获得,参数如下:

  • ARDS结构体

    偏移量 描述
    0 基地址低32位
    4 基地址高32位
    8 内存大小低32位
    12 内存大小高32位
    16 本段内存属性,1可用,2不可用
  • int 0x15参数

    寄存器 描述
    eax 0xe820子功能号,返回时会被设置为ebx的值
    ebx ARDS后续值,初始为0,当没有更多信息时返回为0
    ecx ARDS结构大小,指示BIOS写入的大小,一般为20
    edx 0x534d4150,固定值
    edi 缓冲区,指向ARDS结构体的地址
  • 可用下面代码获得内存大小

    Get_Men:
      push bp
      mov	bp,sp
      sub	sp,0x200
      mov	di,sp
      sub	sp,4
      mov	dword [bp-0x204],0
      mov	edx,0x534d4150
      xor ebx,ebx
    mem_loop:
      mov eax,0xe820
      mov	ecx,20
      int	0x15
      jc	mem_failed
      inc	dword [bp-0x204]
      add	edi,ecx
      cmp	ebx,0
      jnz	mem_loop
      sub	edi,ecx
      mov	ecx,[bp-0x204]
      xor	eax,eax
    mem_max:
      mov	edx,[edi]
      add	edx,[edi+8]
      cmp	eax,edx
      jge	next_one
      mov	eax,edx
    next_one:
      sub	edi,20
      loop mem_max
      leave
      ret
    mem_failed:
      xor	eax,eax
      leave
      ret
    

cr3寄存器保存页目录表的物理地址,cr0寄存器第32位为1表示开启虚拟地址

  • 下面代码将低4M虚拟内存映射到低4M物理内存
    set_virtual_addr:
      mov	eax,0x100000|ADDR_P|ADDR_RW
      mov	[VIRTUAL_DIR_TABLE],eax
      mov	ecx,1023
      mov	edi,4
    loop_zero:
      mov dword [edi],0
      add	edi,4
      loop loop_zero
    
      mov	eax,0 | ADDR_P | ADDR_RW
      mov	edi,0x100000
      mov	ecx,1024
    set_virtual_table:
      mov	[edi],eax
      add	eax,0x1000
      add	edi,4
      loop set_virtual_table
      mov	eax,VIRTUAL_DIR_TABLE
      mov	cr3,eax
      mov	eax,cr0
      or	eax,0x80000000
      mov	cr0,eax