美文网首页
计算机系统基础实验——保护模式

计算机系统基础实验——保护模式

作者: 心若鉴 | 来源:发表于2019-11-25 22:22 被阅读0次

保护模式

预备知识

线性地址:在保护模式下,寻址方式会产生变化。程序给出的32位地址不再直接解释为物理地址,而是相对于某一个段的偏移量(offset)。真正的物理地址由下式给出:
<center>physical address = linear address = base address + offset</center>
其中的base address是一个32位的地址,对应某个段的基地址;而offset则是程序给出的32位段内偏移量。

48位的逻辑地址(或称虚拟地址)

48位逻辑地址结构
段表:其中存储好每个段的首地址(base address)、段的长度(limit)等相关信息。
段描述符:段表由一系列连续的段表项构成,其中每个段表项都是一个64位的数据结构称为段描述符。
在这里插入图片描述
段选择符:高13位是一个index,用于指出所访问段的段描述符是段表中的第几项(数组下标);TI用于指出选择哪一个段描述符表,TI为0时表示选择全局描述符表(GDT),TI为1时表示选择局部描述符表(LDT)。
Alt

汇编指令LGDT

Opcode Instruction Description
OF 01/ 2 LGDT m16&32 Load m into GDTR

IF OperandSize = 16
THEN GDTR.Limit:Base ← m16:24 (* 24 bits of base loaded *)
ELSE GDTR.Limit:Base ← m16:32;

我觉得是指从当前内存连续取6个字节的数据,其中2个字节的数据存到gdtr的limit里,另外4个字节的数据存到gdtr的base里
以上是刚开始如此想的,但是emmm......结果可想而知
正确理解应该是:从当前内存地址cpu.eip处取32位数,这个是一个地址,然后从这个地址开始取48位数,这6个字节的数据,才是将要储存到gdtr寄存器中的数据。
比如,在nemu/src/cpu/instr文件夹中加入lgdt.c文件,内容如下

make_instr_func(lgdt)
{
    OPERAND rel;
    rel.type = OPR_IMM;
    rel.sreg = SREG_CS;
    rel.data_size = 32;
    rel.addr = eip + 2;
    operand_read(&rel);
    
    uint8_t val[6];
    memcpy(&val, hw_mem + rel.val, 6);

    cpu.gdtr.limit = val[0] + (val[1] << 8);
    if(data_size == 16)
        cpu.gdtr.base = val[2] + (val[3] << 8) + (val[4] << 16);
    else
        cpu.gdtr.base = val[2] + (val[3] << 8) + (val[4] << 16) + (val[5] << 24);

    return 1 + 1 + 4;
}

汇编指令LJMP

IF operand type = ptr16:16 or ptr16:32
THEN
IF OperandSize = 16
THEN
CS:IP ← ptr16:16;
EIP ← EIP AND 0000FFFFH; (* clear upper 16 bits )
ELSE (
OperandSize = 32 *)
CS:EIP ← ptr16:32;
FI;
FI;

当开启保护模式后,NEMU中运行的程序访问内存时给出的就不简单是32位的物理地址,而是一个16位的段选择符加上32位的段内偏移量(有效地址)所构成的48位的逻辑地址(或称虚拟地址)。
所以指令ljmp后会跟着6个字节的数据,前2个字节的数据是段选择符(前面已经介绍过了),根据这2个字节的数据,计算出index,然后根据index去寻找段表数组,index是该数组的下标,然后从这个段表项中得到段基地址,另外4个字节的数据是段内偏移量,所以把两个数相加,就是要跳转到的位置。

实现load_sreg()函数

void load_sreg(uint8_t sreg)
{
    SegDesc segDesc;
    memcpy(&segDesc, hw_mem + cpu.gdtr.base + 8 * (cpu.segReg[sreg].index), 8);
    uint32_t base = (segDesc.base_32_24 << 24) + (segDesc.base_23_16 << 16) + segDesc.base_15_0;
    uint32_t limit = (segDesc.limit_19_16 << 16) + segDesc.limit_15_0;
    assert(base == 0);
    assert(limit == 0xfffff);
    assert(segDesc.granularity == 1);
    cpu.segReg[sreg].base = base;
    cpu.segReg[sreg].limit = limit;
}

实验总结

历时许久终于做完了,我太难了

  1. 刚开始对LGDT指令和LJMP指令以及MOV(mov sw, ew与mov (control regsiter) to register)指令的不熟悉,上网上搜了好久没有找到,或者说找到相关的,但是理解不了,所以导致进度一直停滞不前。在一个月黑风高的晚上,闭上眼睛苦思冥想,终于想到了一个,需要花很多时间,但是一定可以做出来的方法,所以从这个想法开始执行到结束,花了不到一天时间,没有执行这个想法之前,停滞了一个多星期没有进展
  2. 注意细节,每一个细节都有可能导致Segment fault,要了解所有可能出现Segment fault的地方,并且加上输出(愚蠢,输出是最愚蠢的办法,但是,实力如此,没办法),然后根据输出去寻找最可能出现错误的地方。
    转载自https://blog.csdn.net/qq_43168521/article/details/102579269

相关文章

  • 计算机系统基础实验——保护模式

    保护模式 预备知识 线性地址:在保护模式下,寻址方式会产生变化。程序给出的32位地址不再直接解释为物理地址,而是相...

  • 2019-04-09

    计算机基础实验5-1 一、实验目的: 练习使用Linux系统调用函数创建进程、加载程序、终止进程、撤销进程,利用信...

  • 笔记 | 计算机系统基础:00-为什么要学这门课?

    课程链接:计算机系统基础(一):程序的表示、转换与链接计算机系统基础(二):程序的执行和存储访问计算机系统基础(三...

  • 实验一

    西 安 邮 电 大学 (计算机学院) 操作系统课内实验报告 实验名称:熟悉Linux操作系统 专业名称:计算机科学...

  • Java 后台开发学习规划

    基础 < > 除GUI编程之外的其他基础部分 <<深入理解计算机系统>>(CSAPP), <<计算机操作系统>> ...

  • 实验室管理系统技术的应用分析

    实验室管理系统技术是指通过计算机对实验室的各种信息进行管理的计算机软、硬件系统。 它以实验室为中心,采用先进的计算...

  • 实验三

    西 安 邮 电 大 学 (计算机学院) 操作系统课内实验报告 实验名称:线程实验 专业名称:计算机科学与技术 班 ...

  • 第一节 Linuix 系统简介

    Linux 基础入门(新版)”实验报告 Linux 系统简介 Linux基础入门(新版)实验报告 实验所得 196...

  • 计算机基础

    计算机基础操作系统计算机网络

  • 操作系统之实模式和保护模式(简图)

    操作系统之实模式和保护模式

网友评论

      本文标题:计算机系统基础实验——保护模式

      本文链接:https://www.haomeiwen.com/subject/ofdswctx.html