zoukankan      html  css  js  c++  java
  • OSLab:实模式与保护模式

    日期:2019/5/18 12:00

    内容:操作系统实验作业;x86;IA-32;实模式与保护模式。

    PS:如果我们上的是同一门课,有借鉴代码的铁汁请留言告知嗷。只是作业笔记,不推荐学习。

    一、实模式

    众所周知,机器启动时都是处于实模式状态的。8多说,先看看今天的作业。

    1.1 BIOS中断打印字符串

    这是一个幼儿园版本的主引导记录(MBR),输出一个字符串,结合附录INT中断说明来看。

    org 0x7c00这个表示程序加载到物理内存的起始地址0x7c00,关于0x7c00请看附录。

        org 0x7c00

        [bits 16]

        mov ax, 0x1301

        mov bx, 0x000c

        mov cx, 5

        mov dx, 0x0808

        mov bp, msg

        int 0x10

        jmp $

    msg:

        db "HELLO", 0

        times 510-($-$$) db 0

        dw 0xaa55

    1.2 直接操纵显卡显示字符串

    实模式下,访问内存的格式:[REG: DISP],其中REG是段寄存器:SS,DS,ES等。DISP是16位的偏移,对应的真实物理地址为(REG<<4)+DISP(20位)。

    VGA全称Video Graphics Array,是一种视频传输标准。

    VGA所使用的视讯内存对应于PC的主内存,它们的真实物理地址为0xA000和0xC000之间的内存。典型地来说位址的开始点是:

    • 0xA000 使用于 EGA/VGA 图型模式(64 KB),0xA000:0000 – 0xA000:FFFF
    • 0xB000 单色文字模式(32 KB),0xB000:0000 – 0xB000:7FFF
    • 0xB800 彩色文字模式和 CGA 相容模式(32 KB), 0xB8000:0000 – 0xB800:7FFF

    注意在0xB800这种模式下,每个VGA字符占2字节,低地址字节是字符的ASCII码,高地址字节是属性值(控制颜色)。每个输出页面是25*80大小。

    例如:

    坐标

    地址1内容

    地址2内容

    说明

    (0,0)

    [0xB800:0000] = 'H'

    [0xB800:0001]=0x0C

    红色的H字符

    (0,1)

    [0xB800:0002] = 'e'

    [0xB800:0003]=0x0C

    红色的e字符

    最大坐标是(24,79)。

    在(0, 0)位置输出红色的X字符。

    org 0x7c00

    [bits 16]

    mov ax, 0xb800

    mov es, ax

    mov ah, 0x0c

    mov al,'X'

    mov [es:0], ax

    jmp $

    times 510-($-$$) db 0

    dw 0xaa55

    1.3 利用VGA输出字符串

    通过循环,基于输出字符X实现。

        org 0x7c00

        [bits 16]

        mov si, msg

        mov bx, 0xb800

        mov es, bx

        mov di, 0

    lab:

        mov ah, 0x0c

        mov al, [si]

        mov [es:di], ax

        add di, 2

        inc si

        cmp al, 0

        jne lab

        jmp $

    msg:

        db "Hello msg from sin", 0

        times 510-($-$$) db 0

        dw 0xaa55

    1.4 清空VGA屏幕

    VGA每个屏幕(显示页)大小为25*80 = 2000。清屏可通过输出2000个ASCII=0的空白字符。

        org 0x7c00

        [bits 16]

        mov ax, 0xb800

        mov es, ax

        mov bx, 0

        mov cx, 0x07d0

    lab:mov dl, 0

        mov dh, 0

        mov [es:bx], dx

        add bx, 2

        loop lab

        jmp $

        times 510-($-$$) db 0

        dw 0xaa55

    二、保护模式

    2.1 GDT与GDTR

    • GDTR

      48位,高32位是GDT(全局描述符表)的基地址base,低16位是limit,表示GDT的界限。32位线性基址部分保存的是全局描述符表在内存中的起始线性地址(不是物理地址,这涉及到内存的段页式管理),16位边界部分保存的是全局描述符表的边界(界限),其在数值上等于表的大小(总字节数-1)。

    base=32bit

    limit=16bit

    GDT最多有几个表项?

    limit=FFFFH,GDT所占字节数为216bytes,每项8个字节,所以最大表项数目 = 213 = 8192。

    • GDT

      GDT其实就是段页式内存管理下的段表嗷,如果不太熟悉建议做一下《微机原理》的作业题。

      GDT的表项分为系统级和用户级。(注意红色标注)

    2.2 CR系列寄存器

    微机原理时间:

    • CR0中含有控制处理器操作模式和状态的系统控制标志;
    • CR1保留不用;
    • CR2含有导致页错误的线性地址;
    • CR3中含有页目录表物理内存基地址,因此该寄存器也被称为页目录基地址寄存器PDBR(Page-Directory Base address Register)。

    对CR0的位进行说明:

    • PG:PG=1分页机制开启
    • ET、TS、EM、MP:协处理器相关。
    • PE:Protect Model Enable,保护模式开启。

    考试坑点:分页机制开启 iff PE = 1 AND PG=1(分页机制一定工作在保护模式下)

    2.3 段选择子

    Segment selector,其实就是段寄存器的值。也就是说,段寄存器在保护模式下,各个字段的含义如下:

    Index字符就是用于索引GDT表项,类似于数组一样:GDT[index]

    2.2 作业:RTFSC

    • 宏定义

    %define CR0_PE          (1 << 0)

    %define CR0_MP          (1 << 1)

    %define CR0_EM          (1 << 2)

    %define CR0_TS          (1 << 3)

    %define CR0_WP          (1 << 16)

    %define CR0_PG          (1 << 31)

    • 数据

      此处gdt定义了3个表项(一共24字节大小)

    gdt: dw 0,0,0,0 ; dummy

     

            dw 0xFFFF ; limit=4GB

            dw 0x0000 ; base address=0

            dw 0x9A00 ; code read/exec

            dw 0x00CF ; granularity=4096,386

     

            dw 0xFFFF ; limit=4GB

            dw 0x0000 ; base address=0

            dw 0x9200 ; data read/write

            dw 0x00CF ; granularity=4096,386

     

            align 8

    gdt_desc:

            dw 23 ; gdt limit=sizeof(gdt) - 1

            dw gdt

     

            times 510-($-$$) db 0

            dw 0xAA55

    • 实模式代码
      • ds=ss=0:ds和ss等寄存器的值与CPU复位的状态有关,为什么是0至今我还不明白。(《微机原理》对这部分有详细的描述)。
      • lgdt指令:GDTR = [gdt_desc],即limit=23放入低16bit(2字节),gdt的起始地址放入base的低2字节(高位全0)。

        为什么没指明段值?实际上就是[cs:gdt_desc]。

      • jmp 0x08: start32:0x08是段值(段选择子),也是就表示选中GDT[1],偏移disp=start32。(PE位开启后,寻址不再是"REG<<4+DISP",此处计算地址的方式需要用"逻辑地址=>线性地址=>物理地址",学过微机原理/组成原理,对这类作业题应该不陌生)
      • ds=es=ss=0x10:表示段页式寻址时,使用GDT[2]。存留疑问:ESP为什么是这个值?

    org 0x7c00

    [bits 16]

    ; First, BIOS loads the bootsector into 0000:7C00.

    cli

    xor ax, ax

    mov ds, ax

    mov ss, ax

    mov sp, 0

     

    ; Switch to protect mode

    lgdt [gdt_desc]

    mov eax, cr0

    or eax, CR0_PE

    mov cr0, eax

    jmp 0x08:start32

    start32:

    ; In protect mode

    cli

    mov ax, 0x10

    mov ds, ax

    mov es, ax

    mov ss, ax

    mov esp, 0x10000

     

    mov al, 'X'

    mov ah, 0x0c

    mov [0xB8000], ax

    jmp $

    align 8

     

    • 保护模式代码

    附录

    INT 0x10中断

    参考:https://blog.csdn.net/yes_life/article/details/6778834

    • 参数说明

      AH=13H的情况下。

      描述:以电传打字机的方式显示字符串

      接受参数:

      AH:0x13

      AL:显示模式

      BH:视频页

      BL:属性值(如果AL=0x00或0x01)

      CX:字符串的长度

      DH,DL:屏幕上显示起始位置的行、列值

      ES:BP:字符串的段:偏移地址

      返回值:    无

      显示模式(AL):

      0x00:字符串只包含字符码,显示之后不更新光标位置,属性值在BL中

      0x01:字符串只包含字符码,显示之后更新光标位置,属性值在BL中

      0x02:字符串包含字符码及属性值,显示之后不更新光标位置

      0x03:字符串包含字符码及属性值,显示之后更新光标位置

    为什么MBR要放在0x7C00

    参考:http://www.ruanyifeng.com/blog/2015/09/0x7c00.html

    注意嗷:MBR在关机的时候是放在磁盘的0号扇区的,开机之后,由BIOS把它加载到内存的嗷。

    主引导记录内存地址设定在比32KB小1024个字节的0x7C00H的位置。(32KB=215=0x7fff)

    是因为Intel第一代cpu8088所搭配的系统最少需要使用32KB的地址空间

    8088本身需要占用0x0000~0x03FF,用来保存各种中断处理程序,内存只剩下0x0400~0x7FFF可使用

    为了把尽量多的连续内存留给操作系统,主引导记录就被放到了内存地址的尾部。

    一个扇区是512字节,主引导记录本身也会产生数据,另外留出一个扇区保存数据。

    为了cpu的向前兼容

    于是0x7c00H便成为了每一代cpu的主引导记录内存地址。

    内存布局图解:

    +--------------------- 0x0

    | Interrupts vectors

    +--------------------- 0x400

    | BIOS data area

    +--------------------- 0x5??

    | OS load area

    +--------------------- 0x7C00

    | Boot sector

    +--------------------- 0x7E00

    | Boot data/stack

    +--------------------- 0x7FFF

    | (not used)

    +--------------------- (...)

  • 相关阅读:
    红帽7 创建网络会话
    红帽7 Iptables与Firewalld防火墙
    红帽7 配置网卡
    红帽7 LVM逻辑卷管理器
    红帽7 RAID磁盘冗余阵列
    红帽7 磁盘划分
    wpf学习一(转)
    选中当前点击的位置
    c#客显
    两个程序间的通信有三种
  • 原文地址:https://www.cnblogs.com/sinkinben/p/10888599.html
Copyright © 2011-2022 走看看