X86系统上的内存分页机制 --页表映射 与 切换页表

在这里插入图片描述

操作系统里面的每一个任务都有自己独立使用的页表,当操作系统切换任务来执行的时候,也要对应的切换页表,另外每一个任务都有自己独立的虚拟地址空间,而每个任务 虚拟地址空间中数据的分布肯定是不一样的,因此会出现这样的情况:同一个虚拟地址 在不同的页表的映射下 ,被转换成了不同的物理地址。

在这里插入图片描述

切换页表实验

%include "inc.asm"

;两个页目录 子页表 起始地址  对应两个不同的任务
;简单的分页构建方法,所有的子页表顺序的连续排列

;页目录起始地址
PageDirBase0    equ    0x200000
;子页表起始地址
PageTblBase0    equ    0x201000

;页目录起始地址
PageDirBase1    equ    0x300000
;子页表起始地址
PageTblBase1    equ    0x301000

org 0x9000

jmp ENTRY_SEGMENT

[section .gdt]
; GDT definition
;                                     段基址,           段界限,       段属性
GDT_ENTRY       :     Descriptor        0,                0,           0
CODE32_DESC     :     Descriptor        0,        Code32SegLen - 1,    DA_C + DA_32
VIDEO_DESC      :     Descriptor     0xB8000,         0x07FFF,         DA_DRWA + DA_32
DATA32_DESC     :     Descriptor        0,        Data32SegLen - 1,    DA_DRW + DA_32
STACK32_DESC    :     Descriptor        0,         TopOfStack32,       DA_DRW + DA_32
;页目录段0 段描述符  最大4096 可读可写,32位保护模式下的段
PAGE_DIR_DESC0  :     Descriptor    PageDirBase0,       4095,          DA_DRW + DA_32
;子页表段 段描述符  最大1024(0--1023)个子页表 可读可写,属性表明 段界限的单位是页(DA_LIMIT_4K) 4K字节,32位保护模式下的段
;默认单位是字节 这里显式的指明了单位是 4K字节
PAGE_TBL_DESC0  :     Descriptor    PageTblBase0,       1023,          DA_DRW + DA_LIMIT_4K + DA_32

;页目录段1 段描述符
PAGE_DIR_DESC1  :     Descriptor    PageDirBase1,       4095,          DA_DRW + DA_32
;子页表段1 段描述
PAGE_TBL_DESC1  :     Descriptor    PageTblBase1,       1023,          DA_DRW + DA_LIMIT_4K + DA_32
; GDT end

GdtLen    equ   $ - GDT_ENTRY

GdtPtr:
          dw   GdtLen - 1
          dd   0
          
          
; GDT Selector

Code32Selector   equ (0x0001 << 3) + SA_TIG + SA_RPL0
VideoSelector    equ (0x0002 << 3) + SA_TIG + SA_RPL0
Data32Selector   equ (0x0003 << 3) + SA_TIG + SA_RPL0
Stack32Selector  equ (0x0004 << 3) + SA_TIG + SA_RPL0
;页目录段0 选择子
PageDirSelector0 equ (0x0005 << 3) + SA_TIG + SA_RPL0
;;子页表段0 选择子
PageTblSelector0 equ (0x0006 << 3) + SA_TIG + SA_RPL0
;页目录段1 选择子
PageDirSelector1 equ (0x0007 << 3) + SA_TIG + SA_RPL0
;子页表段1 选择子
PageTblSelector1 equ (0x0008 << 3) + SA_TIG + SA_RPL0
; end of [section .gdt]

TopOfStack16    equ 0x7c00

[section .dat]
[bits 32]
DATA32_SEGMENT:
    DTOS               db  "D.T.OS!", 0
    DTOS_OFFSET        equ DTOS - $$
    HELLO_WORLD        db  "Hello World!", 0
    HELLO_WORLD_OFFSET equ HELLO_WORLD - $$

Data32SegLen equ $ - DATA32_SEGMENT

[section .s16]
[bits 16]
ENTRY_SEGMENT:
    mov ax, cs
    mov ds, ax
    mov es, ax
    mov ss, ax
    mov sp, TopOfStack16
    
    ; initialize GDT for 32 bits code segment
    mov esi, CODE32_SEGMENT
    mov edi, CODE32_DESC
    
    call InitDescItem
    
    mov esi, DATA32_SEGMENT
    mov edi, DATA32_DESC
    
    call InitDescItem
    
    mov esi, STACK32_SEGMENT
    mov edi, STACK32_DESC
    
    call InitDescItem
    
    ; initialize GDT pointer struct
    mov eax, 0
    mov ax, ds
    shl eax, 4
    add eax, GDT_ENTRY
    mov dword [GdtPtr + 2], eax

    ; 1. load GDT
    lgdt [GdtPtr]
    
    ; 2. close interrupt
    cli 
    
    ; 3. open A20
    in al, 0x92
    or al, 00000010b
    out 0x92, al
    
    ; 4. enter protect mode
    mov eax, cr0
    or eax, 0x01
    mov cr0, eax
    
    ; 5. jump to 32 bits code
    jmp dword Code32Selector : 0


; esi    --> code segment label
; edi    --> descriptor label
InitDescItem:
    push eax

    mov eax, 0
    mov ax, cs
    shl eax, 4
    add eax, esi
    mov word [edi + 2], ax
    shr eax, 16
    mov byte [edi + 4], al
    mov byte [edi + 7], ah
    
    pop eax
    
    ret

    
[section .s32]
[bits 32]
CODE32_SEGMENT:
    mov ax, VideoSelector
    mov gs, ax
    
    mov ax, Stack32Selector
    mov ss, ax
    
    mov eax, TopOfStack32
    mov esp, eax
    
    mov ax, Data32Selector
    mov ds, ax
    
    mov ebp, DTOS_OFFSET
    mov bx, 0x0C
    mov dh, 12
    mov dl, 33
    
    call PrintString
    
    mov ebp, HELLO_WORLD_OFFSET
    mov bx, 0x0C
    mov dh, 13
    mov dl, 31
    
    call PrintString
    
    mov eax, PageDirSelector0
    mov ebx, PageTblSelector0
    mov ecx, PageTblBase0
    
    call InitPageTable
    
    mov eax, PageDirSelector1
    mov ebx, PageTblSelector1
    mov ecx, PageTblBase1
    
    call InitPageTable
    
    mov eax, PageDirBase0
    
    call SwitchPageTable
    
    mov eax, PageDirBase1
    
    call SwitchPageTable
    
    jmp $

; eax --> page dir base selector
; ebx --> page table base selector 
; ecx --> page table base
InitPageTable:
    push es
    push eax  ; [esp + 12]
    push ebx  ; [esp + 8]
    push ecx  ; [esp + 4]
    push edi  ; [esp]
    
    mov es, ax
    mov ecx, 1024    ;  1K sub page tables
    mov edi, 0
    mov eax, [esp + 4]
    or  eax, PG_P | PG_USU | PG_RWW
    
    cld
    
stdir:
    stosd
    add eax, 4096
    loop stdir
    
    mov ax, [esp + 8]
    mov es, ax
    mov ecx, 1024 * 1024   ; 1M pages
    mov edi, 0
    mov eax, PG_P | PG_USU | PG_RWW
    
    cld
    
sttbl:
    stosd
    add eax, 4096
    loop sttbl
    
    pop edi
    pop ecx
    pop ebx
    pop eax
    pop es
    
    ret   

; eax --> page directory base
SwitchPageTable:
    push eax
    
    mov eax, cr0
    and eax, 0x7FFFFFFF
    mov cr0, eax
    
    mov eax, [esp]
    mov cr3, eax
    mov eax, cr0
    or  eax, 0x80000000
    mov cr0, eax
    
    pop eax
    
    ret


; ds:ebp    --> string address
; bx        --> attribute
; dx        --> dh : row, dl : col
PrintString:
    push ebp
    push eax
    push edi
    push cx
    push dx
    
print:
    mov cl, [ds:ebp]
    cmp cl, 0
    je end
    mov eax, 80
    mul dh
    add al, dl
    shl eax, 1
    mov edi, eax
    mov ah, bl
    mov al, cl
    mov [gs:edi], ax
    inc ebp
    inc dl
    jmp print

end:
    pop dx
    pop cx
    pop edi
    pop eax
    pop ebp
    
    ret
    
Code32SegLen    equ    $ - CODE32_SEGMENT

[section .gs]
[bits 32]
STACK32_SEGMENT:
    times 1024 * 4 db 0
    
Stack32SegLen equ $ - STACK32_SEGMENT
TopOfStack32  equ Stack32SegLen - 1
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Linux老A

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值