VV的操作系统笔记(二)保护模式及GDT、LDT

首先来看一段代码

int add_x_y(int x,int y){
	return x+y;
}

通过执行g++ -c test.cpp以后生成obj文件,然后通过objdump -d test.o输出编译后的指令得到

Disassembly of section .text:

0000000000000000 <_Z7add_x_yii>:
   0:	55                   	push   %rbp
   1:	48 89 e5             	mov    %rsp,%rbp
   4:	89 7d fc             	mov    %edi,-0x4(%rbp)
   7:	89 75 f8             	mov    %esi,-0x8(%rbp)
   a:	8b 55 fc             	mov    -0x4(%rbp),%edx
   d:	8b 45 f8             	mov    -0x8(%rbp),%eax
  10:	01 d0                	add    %edx,%eax
  12:	5d                   	pop    %rbp
  13:	c3                   	retq   

从而得到一个程序函数的一个执行过程。学习过操作系统的都了解一个多任务的操作系统中是通过时间轮盘算法来对程序进行调度,使得CPU在不同周期执行着不同的指令,通过汇编代码可以看到每个程序都有着自己的描述符号即LDT局部描述符表来组建对变量和代码之间的符号描述。然而此时还需要一个针对全局的,对计算机运行状态进行控制的全局描述符表GDT(Global Descriptor Table)在整个系统中,全局描述符表GDT只有一张(一个处理器对应一个GDT),GDT可以被放在内存的任何位置.

接下来就到了编写时间、在这之前,需要定义一些数据类型

types.h

typedef unsigned short u_short;
typedef unsigned int u_int;
typedef unsigned char u_char;
typedef unsigned long u_long;
typedef unsigned char uint8_t;
typedef unsigned short uint16_t;
typedef unsigned long uint32_t;
#ifndef FRTOS_GDT_H
#define FRTOS_GDT_H

#include "types.h"

class GlobalDescriptorTable {
public:
    class SegementDescriptor {
    private:
        uint16_t limit_lo;
        uint16_t base_io;
        uint16_t base_hi;
        uint16_t type;
        uint16_t flags_limit_hi;
        uint16_t base_vhi;
    public:
        SegementDescriptor(uint32_t base, uint32_t limit, uint8_t type);

        uint32_t Base();

        uint32_t Limit();

    };

    SegementDescriptor nullSegementDescriptor;
    SegementDescriptor unusedSegementDescriptor;
    SegementDescriptor codeSegementDescriptor;
    SegementDescriptor dataSegementDescriptor;


    GlobalDescriptorTable();
    ~GlobalDescriptorTable();

    uint16_t CodeSegementSelector();

    uint16_t DataSegementSelector();

};

#endif

gdt.cpp

#include "gdt.h"
#include "types.h"


GlobalDescriptorTable::GlobalDescriptorTable() :
        nullSegementDescriptor(0, 0, 0),
        unusedSegementDescriptor(0, 0, 0),
        codeSegementDescriptor(
                0, 64 * 1024 * 1024, 0x9A),
        dataSegementDescriptor(0, 64 * 1024 * 1024, 0x92) {


    uint32_t i[2];
    i[0] = (uint32_t) this;
    i[1] = sizeof(GlobalDescriptorTable) << 16;
    asm volatile("lgdt (%0)": :"p" (((uint8_t *) i) + 2));

}

GlobalDescriptorTable::~GlobalDescriptorTable() {

}

uint16_t GlobalDescriptorTable::DataSegementSelector() {
    return ((uint8_t *) &dataSegementDescriptor - (uint8_t *) this);
}

uint16_t GlobalDescriptorTable::CodeSegementSelector() {
    return ((uint8_t *) &codeSegementDescriptor - (uint8_t *) this);
}
GlobalDescriptorTable::SegementDescriptor::SegementDescriptor(uint32_t base, uint32_t limit, uint8_t flags) {
    uint8_t *target = (uint8_t *) this;
    if (limit <= 65535) {
        target[6] = 0x40;
    } else {
        if ((limit & 0xfff) != 0xfff) {
            limit = (limit >> 12) - 1;
        } else {
            limit = limit >> 32;
        }
        target[6] = 0xc0;
    }
    target[0] = limit & 0xff;
    target[1] = (limit >> 8) & 0xff;
    target[6] |= (limit >> 16) & 0xff;

    target[2] = base & 0xff;
    target[3] = (base >> 8) & 0xff;
    target[4] = (base >> 16) & 0xff;
    target[7] = (base >> 24) & 0xff;

    target[5] = flags;
}


uint32_t GlobalDescriptorTable::SegementDescriptor::Base() {
    uint8_t *target = (uint8_t *) this;
    uint8_t result = target[7];
    result = (result << 8) + target[4];
    result = (result << 8) + target[3];
    result = (result << 8) + target[2];
    return result;

}

uint32_t GlobalDescriptorTable::SegementDescriptor::Limit() {
    uint8_t *target = (uint8_t *) this;
    uint8_t result = target[6] & 0xf;
    result = (result << 8) + target[1];
    result = (result << 8) + target[0];

    if ((target[6] & 0xc0) == 0xc0)
        result = (result << 32) | 0xfff;
    return result;
}

(adsbygoogle = window.adsbygoogle || []).push({});

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

扫码关注云+社区

领取腾讯云代金券