|
马上注册,结交更多好友,享用更多功能^_^
您需要 登录 才可以下载或查看,没有账号?立即注册
x
本帖最后由 nichkhun 于 2012-3-30 17:34 编辑
无奈,要发这个帖子刚弄错了,已经造成自己去删除的时候还扣了不少分。
希望这次能弄对把
我也是才开始学习的,把自己从中学习到的,分享给大家
在此之前很早就有过如此的想法,只是很多大牛在前,让我感觉我所学的真是少之又少,这次鼓足勇气,希望大家踊跃拍砖把
在这里设置1个回复可见,是希望自己的劳动成果不会“沉默”, 当然也希望大家能鼓励我,我争取会把这手记写完!
---------------------------------------------------------------------------------------------------------------------------------
通过昨天晚上关灯后,在寝室仔细翻阅了下系统的书,相比以前看硬件的书要强上了许多,起码概念和原理能靠拢了.
看的都是很杂的汇编书,和机制原理,有点偏了.集中记录下我的学习收获
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
有关IA32的介绍,请看这个网站: http://www.kerneltravel.net/chenlj/lecture2.pdf
GDT详细介绍 http://blog.csdn.net/zdwzzu2006/article/details/4030882
PE的详细学习视频介绍 http://www.fishc.com/a/shipin/jiemixilie/list_119_2.html
描述符属性 http://www.cppblog.com/xingkongyun/articles/62743.html
代码借鉴 于渊
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
************************************************************************************************************************
前言 实模式和保护模式
在IA32下, CPU是具有两种工作模式的, 实模式和保护模式, 当我们打开自己的PC, 在最开始时候是在CPU的实模式下跑
经过某某机制运行后,我们开是进入了系统提供更好的硬件保障,到达了保护模式,如果说这样理解有点困难的话,(那举个更
简单的例子,当你开机的时候,屏幕是黑黑的,那就是在实模式时候,开机了说欢迎WINDOW7,那说明你就进入了保护模式了,前提
你是WIN7用户否则怎么是欢迎你WIN7了呢。。)
在旧的政策年代,9X年代,Intel8086,是1个16位的CPU,拥有16个寄存器, 16个数据总线, 以及20位地址总线. 还有1个1MB的
寻址能力, 1个地址是有段地址加上偏移地址构成的,
公式如示 物理地址(Physical Address) = 段地址(Segment) * 16 + 偏移(Offset)
在这里,地址和偏移都是16位的
在保护模式下,CPU是32时代, 也就是我们所说的80X86, 有32位地址线和4GB的寻址空间
在保护模式下"段"的概念发生了根本性的变化,
在实模式时候,我们可以将地址看做成,段值XXXXh, 来表示以XXXX0h的开始内存.
而保护模式下, 段的起始地址却是由CS, DS, 等寄存器去索引了. 指向的是数据结构的表项,
而表项详细定义了段的起始地址, 界限, 属性等内容, 这个数据结构, 就是GDT, 专用名词, 描述符, (Descriptor)
**************************************************************************************************************************
%include "pm.inc" ; 常量, 宏, 以及一些说明
org 0100h
jmp LABEL_BEGIN
[SECTION .gdt]
; GDT
; 段基址, 段界限 , 属性
LABEL_GDT: Descriptor 0, 0, 0 ; 空描述符
LABEL_DESC_CODE32: Descriptor 0, SegCode32Len - 1, DA_C + DA_32; 非一致代码段
LABEL_DESC_VIDEO: Descriptor 0B8000h, 0ffffh, DA_DRW ; 显存首地址
; GDT 结束
GdtLen equ $ - LABEL_GDT ; GDT长度
GdtPtr dw GdtLen - 1 ; GDT界限
dd 0 ; GDT基地址
; GDT 选择子
SelectorCode32 equ LABEL_DESC_CODE32 - LABEL_GDT
SelectorVideo equ LABEL_DESC_VIDEO - LABEL_GDT
; END of [SECTION .gdt]
[SECTION .s16]
[BITS 16]
LABEL_BEGIN:
mov ax, cs
mov ds, ax
mov es, ax
mov ss, ax
mov sp, 0100h
; 初始化 32 位代码段描述符
xor eax, eax
mov ax, cs
shl eax, 4
add eax, LABEL_SEG_CODE32
mov word [LABEL_DESC_CODE32 + 2], ax
shr eax, 16
mov byte [LABEL_DESC_CODE32 + 4], al
mov byte [LABEL_DESC_CODE32 + 7], ah
; 为加载 GDTR 作准备
xor eax, eax
mov ax, ds
shl eax, 4
add eax, LABEL_GDT ; eax <- gdt 基地址
mov dword [GdtPtr + 2], eax ; [GdtPtr + 2] <- gdt 基地址
; 加载 GDTR
lgdt [GdtPtr]
; 关中断
cli
; 打开地址线A20
in al, 92h
or al, 00000010b
out 92h, al
; 准备切换到保护模式
mov eax, cr0
or eax, 1
mov cr0, eax
; 真正进入保护模式
jmp dword SelectorCode32:0 ; 执行这一句会把 SelectorCode32 装入 cs,
; 并跳转到 Code32Selector:0 处
; END of [SECTION .s16]
[SECTION .s32]; 32 位代码段. 由实模式跳入.
[BITS 32]
LABEL_SEG_CODE32:
mov ax, SelectorVideo
mov gs, ax ; 视频段选择子(目的)
mov edi, (80 * 11 + 79) * 2 ; 屏幕第 11 行, 第 79 列。
mov ah, 0Ch ; 0000: 黑底 1100: 红字
mov al, 'P'
mov [gs:edi], ax
; 到此停止
jmp $
SegCode32Len equ $ - LABEL_SEG_CODE32
; END of [SECTION .s32]
*********************************************************************(在这里,你先不用怎么关心这段代码的意思)
首先,我来介绍下第一位上场的人员GDT(Global Descriptor Table)
GDT的作用是用来提供段式存储机制的, 这种机制是通过段寄存器和GDT中的描述符共同提供的
代码段和数据段描述符是由4个成员组成的 段基址, 属性, 段基址, 段界限
属性是是1个比较纠结的东西,所以我留下了个参考网站。- - ||
在这段代码中,有3个描述符LABEL_GDT, LABEL_DESC_CODE32, LABEL_DESC_VIDEO
cs, ds段寄存器对应的是
mov ax, SelectorVideo
mov gs, ax
注意(SelectorVideo equ LABEL_DESC_VIDEO - LABEL_GDT)这个是选择子,他并不是偏移他里面涉及到了描述符, TI和RPL
段:偏移的形式仅仅是人们逻辑上的地址,同样经过了机制转换后转换为 “线性地址” (线性地址和物理地址是差不多的概念.)
在[SECTION .s16]中
; 初始化 32 位代码段描述符
xor eax, eax
mov ax, cs
shl eax, 4
add eax, LABEL_SEG_CODE32
mov word [LABEL_DESC_CODE32 + 2], ax
shr eax, 16
mov byte [LABEL_DESC_CODE32 + 4], al
mov byte [LABEL_DESC_CODE32 + 7], ah
对LABEL_DESC_CODE32进行了初始化工作
接下来,关闭中断
cr0的0位是PE位,此为为0,就是跑在实模式下,转换为1,就可以跑在保护模式下了。
最后
就是这么多把- -。感想真多啊,或许写的很少,但是却足足花了我一些时间去仔细总结和分析,很怕出错,如有BUG,请联系我
|
|