• linkedu视频
  • 平面设计
  • 电脑入门
  • 操作系统
  • 办公应用
  • 电脑硬件
  • 动画设计
  • 3D设计
  • 网页设计
  • CAD设计
  • 影音处理
  • 数据库
  • 程序设计
  • 认证考试
  • 信息管理
  • 信息安全
菜单
linkedu.com
  • 网页制作
  • 数据库
  • 程序设计
  • 操作系统
  • CMS教程
  • 游戏攻略
  • 脚本语言
  • 平面设计
  • 软件教程
  • 网络安全
  • 电脑知识
  • 服务器
  • 视频教程
  • JavaScript
  • ASP.NET
  • PHP
  • 正则表达式
  • AJAX
  • JSP
  • ASP
  • Flex
  • XML
  • 编程技巧
  • Android
  • swift
  • C#教程
  • vb
  • vb.net
  • C语言
  • Java
  • Delphi
  • 易语言
  • vc/mfc
  • 嵌入式开发
  • 游戏开发
  • ios
  • 编程问答
  • 汇编语言
  • 微信小程序
  • 数据结构
  • OpenGL
  • 架构设计
  • qt
  • 微信公众号
您的位置:首页 > 程序设计 >Android > Linux内核系列—操作系统开发之进入32位保护模式,linux保护模式

Linux内核系列—操作系统开发之进入32位保护模式,linux保护模式

作者:网友 字体:[增加 减小] 来源:互联网 时间:2017-05-26

网友通过本文主要向大家介绍了linux内核 文件操作,linux内核,linux内核完全剖析,linux内核源码下载,linux内核下载等相关知识,希望对您有所帮助,也希望大家支持linkedu.com www.linkedu.com

Linux内核系列—操作系统开发之进入32位保护模式,linux保护模式


源码如下:

; ==========================================
; pmtest1.asm
; 编译方法:nasm pmtest1.asm -o pmtest1.bin
; ==========================================

%include	"pm.inc"	; 常量, 宏, 以及一些说明

org	07c00h
	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,
					; 并跳转到 SelectorCode32: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]

运行结果如下,在屏幕最右边有一个红色的P:

源码解析:

1.首先程序跳转至LABEL_BEGIN处,jmp LABEL_BEGIN。将ds、es、ss段寄存器全部初始化为当前代码段。

2.初始化32位代码段描述符

在实模式下,也就是8086的16位的CPU的寻址方式是段x16+偏移,而在保护模式下,段寄存器值变成了一个索引,这个索引指向段描述符,也就是GDT中对应的那个描述符,描述符中包含了最终的基地址。

 38-41行表示将当前程序代码段左移4位也就是x16,再加上LABEL_SEG_CODE32的偏移地址,最终形成LABEL_SEG_CODE32的物理地址,42-45表示把此物理地址加载到段描述符对应的段基址位置,段描述符格式如下图所示

段基地址0-15位也就是LABEL_DESC_CODE32 + 2地址处,将16位的ax传入,第43行向右移动16位表示已经传入的16位消除,然后将剩余的两个8位高低寄存器值传入对应的段基地址处。

Descriptor是在pm.inc中定义的宏,如下图所示,表示的就是段描述符的格式:

3.加载GDTR,GDRT的结构图如下所示

GDTR是唯一的一个指向段描述符表的寄存器,48-55行就是把段描述符表的基地址加载到GDTR寄存器当中。48行清除eax值,49-52是把LABEL_GDT的物理地址加载到20行的GdtPtr的双字处,也就是GDT基地址。55行把GdtPtr地址的内容加载到GDTR,双字节dw对应的是16位界限,双字dd对应的是32位基地址。

4.关中断和打开A20

保护模式下中断处理机制和实模式不同,所以先关闭中断,指令为cli。打开A20为历史原因防止偏移超出最大值时回滚。58-63行

5.切换到保护模式

只要把寄存器cr0的第0位置为1就行了。66-68行

6.真正进入保护模式

jmp dword SelectorCode32:0,这一行是真正进入保护模式的代码,SelectorCode32是个段选择子,段选择子的作用是找到对应的段描述符从而找到对应的段基地址。段选择子的格式如下图所示

从位3开始表示为段描述符表的索引,这句代码执行完之后就会把描述符LABEL_DESC_CODE32中的段基址也就是LABEL_SEG_CODE32加载到cs。

dword的作用是因为当前还是16位的代码,如果没有dword,SelectorCode32:0的偏移地址如果超出16位那么只会截取16位。

 

到此已经完全进入32位保护模式了。

分享到:QQ空间新浪微博腾讯微博微信百度贴吧QQ好友复制网址打印

您可能想查找下面的文章:

  • Linux内核系列—11.操作系统开发之ELF格式,linuxelf
  • Linux内核系列—7.操作系统开发之中断和异常,linux内核
  • Linux内核系列—6.操作系统开发之内存分页机制,linux分页
  • Linux内核系列—4.操作系统开发之LDT,linuxldt
  • Linux内核系列—操作系统开发之保护模式的优势,linux内核
  • Linux内核系列—操作系统开发之进入32位保护模式,linux保护模式
  • Linux内核系列—操作系统开发之HelloWorld,linuxhelloworld

相关文章

  • 2017-05-26easy touch利用playmaker拖动ngui对象
  • 2017-05-26Android5.0开发范例大全 读书笔记(五),android5.0范例
  • 2017-05-26向量时钟算法简介
  • 2017-05-26Android开发3:Intent、Bundle的使用和ListView的应用 、RelativeLayout(相对布局)简述(简单通讯录的实现),relativelayout
  • 2017-05-26iTween基础之功能简介,itween功能简介
  • 2017-05-26网上商城4--首页二级分类的查询,4--二级分类
  • 2017-05-26我的第一篇博客,我试试怎么用,第一篇博客,试试
  • 2017-05-26[Android] android.util.Log,android.util.logjar
  • 2017-05-26测试经验总结之--测试员的角色
  • 2017-05-26Android学习笔记-开关按钮ToggleButton和开关Switch,togglebuttonswitch

文章分类

  • JavaScript
  • ASP.NET
  • PHP
  • 正则表达式
  • AJAX
  • JSP
  • ASP
  • Flex
  • XML
  • 编程技巧
  • Android
  • swift
  • C#教程
  • vb
  • vb.net
  • C语言
  • Java
  • Delphi
  • 易语言
  • vc/mfc
  • 嵌入式开发
  • 游戏开发
  • ios
  • 编程问答
  • 汇编语言
  • 微信小程序
  • 数据结构
  • OpenGL
  • 架构设计
  • qt
  • 微信公众号

最近更新的内容

    • Android Studio项目提交到GitHub,androidgithub
    • Tips:datapump异常中断后的处理
    • android Android性能优化之如何避免Overdraw,androidoverdraw
    • Android 退出app,后台推送的服务也停止了,怎么可以做到不停止后台服务呢?,androidapp
    • Android—基于微信开放平台v3SDK,开发微信支付填坑。,androidv3sdk
    • Install Battery Historian,batteryhistorian
    • FragmentTabHost的基本用法,fragmenttabhost
    • 抽取的BaseFragment和LoadingPage,basefragment
    • android--获取屏幕高宽度工具类,android--工具类
    • 如何取得nginx做反向代理时的真实IP?

关于我们 - 联系我们 - 免责声明 - 网站地图

©2020-2025 All Rights Reserved. linkedu.com 版权所有