操作系统引导--从实模式到保护模式
从开始到保护--系统开机引导
------没有一个文档能写的通俗易懂,我希望写出来。
开机引导和实模式:
两个星期加上假期吐血整理,所述为计算机的开机引导,其中包括一系列计算机内存设置等等,由于没有老师教,本人理解可能还是有点错误,希望错误的地方看的博友们能帮忙指出来,共同学习,谢谢!
目前正在看linux0.11内核源代码,参考资料极其环境配置后面会说出来。
我们的操作系统从计算机加电开始就开始运行,那么,爱思考的同学们会问计算机的运行最起码都是从内存运行的,运行的是内存的代码,那么在开机启动的时候计算机内存里面是不会有东西的,那么,到底操作系统是怎么启动的呢?
其实从计算机加电开始,操作系统首先进行一系列自检,这个自检是通过计算机加电然后发送一个信号给BIOS,BIOS进行一部分代码复制来初始化计算机(这里的代码复制的是一个固定ROM区里面的?),初始化完毕后计算机就开始自动读取磁盘,磁盘读取一个扇区,512字节,当独到某个磁盘第0磁道第一个扇区的最后两个字节为55和aa的时候计算机就自动认为其为引导程序,就会把此512字节读入内存绝对地址0x07c00处。此时,计算机的操作就完全交给程序设计者了。
那么,也就是说引导系统必须具备如下因素:
1、加载到0x7c00处
2、大小为512字节
3、最后两个字节为55和aa
满足这三个条件的程序都可以作为引导,只要将其写入磁盘的第0磁道第一扇区处即可成为引导。
说到这里,有一件比较有意思的事情,去年一学弟说自己写了个病毒,破坏磁盘,当时就想想这个是个硬件问题,前几天突然想了想,不能启动系统不就是引导坏了吗?这个是可以修的,只要将程序写入磁盘,不就OK了吗,遂要那个代码,可惜代码没了,貌似在现在的windows系统里面直接写汇编读写磁盘就是不行,保护太强了,不知道他是怎么实现的破坏磁盘。
这里说一点常识:这里说的写入磁盘的代码是二进制的代码,就是纯二进制,也就是机器码,那么在windows里面(由于目前我是在windows里面开发的,windows的批处理很好用,而Linux的GNU make现在还不会用)是一种.com文件,用masm汇编的话可以这样将exe文件转换成com文件:
Exe2bin a.exe a.com
而如果使用nasm汇编的话直接编译成.bin文件就行了:
nasm -o boot.bin boot.asm
编译好后的com文件可以直接双击执行,而bin文件可以使用二进制查看,也可以自己写程序打开查看,都可以使用debug调试,这两种文件区别是com在内存定位为0x0100处,而bin文件不确定,由于windows的保护,也可能是一致的。
在这里不得不提到:在最初计算机自检完成后将磁盘内容读入内存的时候,dl寄存器中存的是本磁盘的磁盘号,所以可以直接保存(???)。
看了这个你可可以写个引导程序试试哦~~~
学过汇编和机组的同学知道,我们老师讲的计算机8086是20根地址线,那么我们的通用寄存器和段寄存器什么的都是16位的,关于如何寻址汇编书上讲了,我想说的是:20根地址线,寻址能力是2^20=1MB,也就是说,cpu最多只能访问1MB内存,那么现在我们的计算机有的都4GB内存该怎么办呢?
计算机加电的时候其实就是按照8086的寻址方式来寻址,只能访问1MB内存,这个能访问1MB内存的状态我们称为实模式,而把能寻址更多的内存的模式称为保护模式,先看看计算机加电后能访问的这1MB内存中内容分布(来自《操作系统引导探究》 谢煜波):
很显然我们在实模式下有一部分内存是不可动的,我们能改变的只是自由内存区和引导程序加载区,比如你如果动了中断向量表区,那么调用BIOS中断将会出错。
关于中断向量表和显示内存曲读者可以参照齐志儒 高福祥《汇编语言程序设计》。
大家都知道,实模式下的内存寻址是直接在段寄存器里面设置段地址的高16位,即绝对内存的高16位,而后后面使用偏移地址定位内存,而在32位保护模式下则不行。
32位保护模式下的寻址:
在32位保护模式下cpu是通过内存分段来寻址的。首先我们来大体看一下分段的寻址:在分段机制中,将大内存分为很多个小的单位:段,段的首地址和长度是特定保存在一个索引中的,索引的首地址是特定保存的,当cpu想访问某一块内存的时候可以指明是哪个段比如说是第N个段,然后根据段的索引的首地址和N来确定是在索引中的哪个项,根据索引中的第N(这个权且当作第N项,其实是第N+1项,后面说明)保存的信息来找到特定的内存地址:
相信读者已经明白了分段了,就是用一块固定内存存储内存的段目录,将目录首地址保存,通过选择目录的第几项来选择段。那么这个在硬件是怎么实现的呢?
大体概括如下:
在Intel的计算机中是使用一个寄存器来保存段的目录的首地址:GDTR寄存器,称为全局描述符表寄存器,而那么段的目录(实际是一张表)称为全局描述符表,英文名叫GDT,用来描述全局的内存。
事实上,与全局描述符表寄存器对应的还有个局部描述符表寄存器。这里暂时不介绍。
另外,还有个寄存器用来选择使用目录里面的哪个段,这个寄存器我们称为“段选择子”。
那么先来看看第一个寄存器:GDTR,即全局描述符表寄存器:
GDTR是一个48位(6字节)寄存器,低16位用于存储段的索引长度,即全局描述符表长度,称为表限,以1字节为一单位(后面说到其实就是全局描述符的个数)。高32位用来存储描述符表的基址。具体如下(来自《操作系统引导探究》 谢煜波):
这里比如我们想设置全局描述符表的基址为0x10000000(记住这里是32位),描述符表共有0x7fff个字节长,那么,就设置GDTR为0x100000007fff即可。
这里,首先告诉你目录(即全局描述符表寄存器)里面的每个项,即每个全局描述符长为8字节。
再介绍段选择子:
段选择子也是一个寄存器,共16位,用来存储使用第几个段和这个段的部分属性。如下(来自《操作系统引导探究》 谢煜波):
这里的索引值就是指的第几个段,占这个16位寄存器的高13位,比如,我想使用第一个段,那么可以设置高13位为1,也是可以说,段的选择位只有13位,共可寻址2^13=8192个段,多了就寻址不到了,前面说过,每个描述符8个字节,那么可以知道,这个目录(全局描述符表)最大可以有8192*8=64KB。
TI是个标志,TI=0时表示此选择子是个全局描述符的选择子,为1时表示这是个局部描述符的选择子,此处可以知道,全局描述符的选择子和局部描述符的选择子其实是同一个寄存器。
RPL为特权级,共有四个特权级,最高特权级为00,表示最底层的操作。
最后来说说那个目录,即全局描述符表:
全局描述符表是由一个一个的全局描述符组成的,每个描述符8字节,共64位,这64位的作用和分布如下(来自《操作系统引导探究》 谢煜波):
这里首先来看看段限部分,段限顾名思义就是段的长度限制,也就是本描述符所描述的段最大可以有多长,从图上可以看出来,段限分为两部分,共20位,而段的长度的单位是由G标志来控制的,G=0表示长度的单位为1字节,G=1表示长度的单位为4KB。比如G=0而段限为100,那么,此段的大小为1B*100=100B,而如果G=1而段限为100,那么此段大小为4KB*100+4KB=404KB(注意,这里的段限是指向头的,需要加4KB)。
这里还可以看出来,段基址也被分为两部分,共32位基址,段的基址就是这个段在内存中的开始地址,这里需要指出的是,段的基址为此段可访问的开始地址,加上段限就是此段可访问的地址,那么如果段限为0的话此段还是可以访问开始地址的,这里不深究。
其他的位作用如下(来自《操作系统引导探究》 谢煜波):
TYPE: 表明此段的类型,4 位中的最高位被清 0 的时候表是它是数据段,相应的余下的三位,从左到右依次为 E、W、A,即数据段的 TYPE 为:0EWA。其中 E 表示向下增长位,置 1 时表示向下增长(这主要是在大小需要动态改变的堆栈段中使用,如果是向下增长的段,动态的改变段的大小限制,会让堆栈空间加到堆栈的底部。如果堆栈的大小不需要改变,那么这个段既可以是向下增长的段,也可以是非向下增长的段) ;W 表示可写位,置 1表示可写;A表示被访问位(如果 CPU访问了它,此位将会被置 1) 。
4 位中的最高位被置 1 时表示它是代码段,相应的余下的三位,从左到右依次为 C、R、A,即代码段的 TYPE 为:1CRA。其中 C 是表明此代码段是否是一致代码段,如果 C 被置1,表明此是一致代码段。一致代码段主要是用于特权级访问控制,这在以后的实验报告中会详细论述;R 表明此段是否可读,置 1 表示可读;A表示被访问位,这与前述一样。
S:为 1 时表示这是一个代码段或数据段描述符,为 0 时表示这是一个系统段描述符。
系统段描述符又称为特殊段描述符, 包括: 局部描述符表 (LDT) 描述符, 任务状态段 (TSS)描述符,调用门描述符,中断门描述符,陷阱门及任务门描述符等。
DPL:表示特权级,从 00~11,共 0,1,2,3 四个特权级
P:为 0 是表示此描述符无效,不能被使用
AVL:留给程序员随便用的
D/B:为 0 的时候表示它是一个 16 位的段,为 1时表示它是一个 32 位的段
设置这些寄存器什么的在汇编里面都有特定的伪指令对应。
介绍完分段模式,不知道你是否已经了解了呢,如果还有疑问的话请直接留言或者发送邮件到qdtecwanli@sina.com,我们大家一起学习哦~
进入保护模式:
在由实模式到保护模式的最大的问题就是内存访问的问题了,现在内存访问问题解决了,那么怎么进入实模式呢?
很明显要设置GDTR,还有打开A20地址线,一般还要初始化8259A中断控制器,最后一步就是设置CR0控制寄存器,你可能不知道我在说什么,没关系,我一个个介绍。
进入保护模式下后,段寄存器内存的不是绝对地址,而是段选择子的值,例如,我的全局描述符表的第三项是数据段,那么我想将数据段装入DS寄存器,我只需要设置段选择子的高十三位为2(从0开始)即可,比如后三位为000,那么段选择子为0000 0000 0001 0000即0x0010。现在就是
Mov ax,0x0010
Mov ds,ax
即可设置数据段寄存器。
GDTR不介绍了。
A20地址线:
(来自http://hi.baidu.com/yvoilee/blog/item/901476ee40a7a12badafd5e3.html ):
1981 年8 月,IBM 公司最初推出的个人计算机IBM PC 使用的CPU 是Intel 8088。在该微机中地址线只有20 根(A0 – A19)。在当时内存RAM 只有几百KB 或不到1MB 时,20 根地址线已足够用来寻址这些内存。所以寻址范围是2^20 = 1M,但8086/8088是16位的地址模式,即只能表示FFFFH(64K)的范围。为了能访问1M的内存采取了分段的模式。
16位段基址:16位偏移,0XFFFF:0XFFFF达到了0X10FFEF,因为8086/8088的内存不可能超过1MB,所以当时的程序超过1MB时会自动回卷至0X0FFEF。
但是到了80286地址线达到24跟。而386达到32根。芯片也达到32-bit。寻址能力达到4GB。但是为了向后兼容IBM采用了一个控制方法。使用一个开关来开启或禁止0x100000 地址比特位。由于在当时的8042键盘控制器上(注意是键盘控制器上的控制线,而不是地址线的第20根)恰好有空闲的端口引脚(输出端口P2,引脚P21),于是便使用了该引脚来作为与门控制这个地址比特位。该信号即被称为A20。如果它为零,则20-31的地址线全部被清除,从而实现了兼容性。操作系统从实模式进入保护模式之前要打开A20地址线。
所以,如果A20被禁止,可访问的内存只能是奇数段(2N+1)M,只有当A20被打开的时候才能访问连续的内存。
只有A20打开才能进入保护模式。
下面讨论一下如何打开A20地址线:
从理论上讲,打开A20 Gate的方法是通过设置8042芯片输出端口(64h)的2nd-bit,但事实上,当你向8042芯片输出端口进行写操作的时候,在键盘缓冲区中,或许还有别的数据尚未处理,因此你必须首先处理这些数据。
所以,激活A20地址线的流程为:
1.关闭中断;
2.等待8042 Input buffer为空;
3.发送禁止键盘操作命令;
4.等待8042 Input buffer为空;
5.发送读取8042 Output Port命令;
6.等待8042 Output buffer有数据;
7.读取8042 Output buffer,并保存得到的字节;
8.等待8042 Input buffer为空;
9.发送Write 8042 Output Port命令到8042 Input buffer;
10.等待8042 Input buffer为空;
11.将从8042 Output Port得到的字节的第2位置1(或清0),然后写入8042 Input buffer;
12.等待,直到8042 Input buffer为空为止;
13.发送允许键盘操作命令到8042 Input buffer;
14. 打开中断。
下面是完成打开A20 Gate的代码:
A20Enable:
cli ;1.关闭中断
call WaitInbufEmpty ;2.等待8042 Input buffer为空;
mov al, 0adh
mov dx, 64h
out dx, al ;3.发送禁止键盘操作命令
call WaitInbufEmpty ;4.等待8042 Input buffer为空;
mov al, 0d0h
mov dx, 64h
out dx, al ;5.发送读取8042 Output Port命令;
call WaitOutbufFull ;6.等待8042 Output buffer有数据;
mov dx, 60h
in al, dx ;7.读取8042 Output buffer
push ax ;保存读取的数据
call WaitInbufEmpty ;8.等待8042 Input buffer为空;
mov al, 0d1h
mov dx, 64h
out dx, al ;9.发送写 8042 Output Port命令
call WaitInbufEmpty ;10.等待8042 Input buffer为空
pop ax
or al, 02h ;11.将从8042 Output Port得到的字节的bit 1置1
mov dx, 60h
out dx, al ;写入Output Port
call WaitInbufEmpty ;12.等待8042 Input buffer为空
mov al, 0aeh
mov dx, 64h
out dx, al ;13.发送允许键盘操作命令
sti ;开中断
ret WaitInbufEmpty:
mov dx, 64h
in al, dx ;读取Status Register
test al, 02h
jnz WaitInbufEmpty
retWaitOutbufFull:
mov dx, 64h
in al, dx
test al, 01 ;读取Status Register
jz WaitOutbufFull
ret
后来,由于感觉使用8042控制A20运行太慢了(确实,那么长的代码,中间还要若干次的wait),所以后来又出现了所谓的Fast A20,实际上,现在的大多数机器都是Fast A20,Fast A20使用92h端口控制A20,同时BIOS里提供了一个软中断来控制A20:
入口:ah=24h
al=0 关闭A20
1 打开A20
2 读取A20状态
int 15h
返回:如果BIOS支持此功能,CF=0,否则CF=1
CF=0时,AX返回当前A20状态,1=打开,0=关闭
像8042中的Output Port中的定义一样,92h端口的bit 1控制着A20,为1时打开,为0时关闭,从92h中读一个byte可以看a20的当前状态,所以对92h的操作如下:
读A20状态
mov dx, 92h
in al, dx
如果al的bit 1为1表示a20打开,否则为0
打开A20
mov dx, 92h
mov al, 02
out dx, al
关闭A20
mov dx, 92h
mov al, 0
out dx, al
8259A中断控制器:
有关8259A可以参看齐志儒、高福祥《汇编语言程序设计》第240页,特别是端口的设置,初始化等。
CR0控制寄存器:
关于控制寄存器,其实是有4个,分别为CR0~CR3,结构如下:
其中,要想开启保护模式,需要将CR0的PE位。当真正置位时,cpu才会真正运行在保护模式下。
为了配合实践,特意使用了下面引导程序来说明(语言:nasm):
boot.asm:
org 0x7c00 ;;定位到0x7c00处
jmp start
SETUPSEG equ 0x9000 ;;将setup程序读到内存的绝对地址
DATASEG equ 0x8000 ;;一般数据的保存地址
ROOT_DEV db 0 ;;启动设备号
start:
mov ax,cs
mov ds,ax
mov es,ax
mov ss,ax
mov [ROOT_DEV],dl ;;保存启动设备号
call load_msg ;;显示启动信息
mov ax,DATASEG
mov ds,ax
mov [0],dl ;;将设备号保存至0x8000:0x0000处
mov ax,cs
mov ds,ax
load_setup: ;;从磁盘的第二扇区读取1KB至0x9000:0x0000处
mov ax,SETUPSEG
mov es,ax
xor bx,bx
mov ax,0x0202
mov dl,[ROOT_DEV]
mov dh,0
mov cx,0x0002
int 0x13 ;;磁盘读取
jnc ok_load_setup
mov ax,0
mov dx,0
int 0x13 ;;磁盘复位
jmp load_setup
ok_load_setup:
jmp SETUPSEG:0x0000
load_msg:
call load_curser
mov ax,loadmessage
mov cx,18
mov bp,ax
mov ax,0x1301
mov bx,0x000c
int 0x10
ret
load_curser:
mov ah,0x03
xor bh,bh
int 0x10
ret
loadmessage db "Booting diers..."
db 13,10
times 510-($-$$) db 0 ;;保证512字节
dw 0xaa55 ;;设置引导标志
set.asm:
org 0x0000
jmp start
SETUPSEG equ 0x9000
DATASEG equ 0x8000
SETSEG equ 0x0400 ;;set程序读入0x9000:0x0400处
gdtaddr: ;;GDTR寄存器的值
dw 0x7fff
dw gdt
dw 0x0009
gdt:
gdtnull:
dw 0,0,0,0 ;;第一个描述符没用,但是需要存在
gdtsyscode: ;;第一个代码段
dw 0x07ff
dw 0x0000
dw 0x9a00
dw 0x00c0
gdtsysdata: ;;第一个数据段
dw 0x07ff
dw 0x0000
dw 0x9200
dw 0x00c0
idtaddr: ;;IDTR的值,暂时设置为空
dw 0x000
dw 0x000
dw 0x000
start:
call load_msg ;;显示信息
mov ax,DATASEG
mov ds,ax
mov dl,[0]
mov bx,SETSEG
mov ax,0x0208
mov dh,0
mov cx,0x0004
int 0x13 ;;读取set程序员
jnc ok_load_set
mov ax,0
mov dx,0
int 0x13 ;;磁盘复位
jmp start
ok_load_set:
;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;; 此处可以自由添加代码,硬件检测等
;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
call open_a20 ;;打开A20地址线
cli ;;关闭全部中断
call move_set ;;将set程序移动到0x0000:0x0000处
lgdt [gdtaddr] ;;设置GDTR的值
lidt [idtaddr] ;;设置IDTR的值
call init_8259a ;;初始化8259A
call set_cr0 ;;设置CR0的值
jmp 0x8:0x0 ;;跳到第一个代码段
load_msg:
call load_curser
mov ax,cs
mov es,ax
mov ax,loadmessage
mov cx,16
mov bp,ax
mov ax,0x1301
mov bx,0x000c
int 0x10
ret
load_curser:
mov ah,0x03
xor bh,bh
int 0x10
ret
open_a20:
mov ah,0x24
mov al,1
int 0x15
ret
move_set:
cld
mov ax,SETUPSEG
mov ds,ax
mov si,SETSEG
mov ax,0x0000
mov es,ax
xor di,di
mov cx,2048
rep movsw
ret
init_8259a:
mov al,0x11
out 0x20,al
call io_delay
out 0xa0,al
call io_delay
mov al,0x20
out 0x21,al
call io_delay
mov al,0x28
out 0xa1,al
call io_delay
mov al,0x04
out 0x21,al
call io_delay
mov al,0x02
out 0xa1,al
call io_delay
mov al,0x01
out 0x21,al
call io_delay
out 0xa1,al
call io_delay
mov al,0xff
out 0x21,al
call io_delay
out 0xa1,al
call io_delay
ret
io_delay:
mov bx,bx
mov bx,bx
mov bx,bx
ret
set_cr0:
mov eax,cr0
or eax,1
mov cr0,eax
ret
loadmessage:
db "Setup diers..."
db 13,10
times 1024-($-$$) db 0
set.asm:
[BITS 32]
org 0x0
jmp start
start:
mov ax,0x10
mov ds,ax
xor esi,esi
mov cl,'a'
mov dl,0x04
show: ;;设置显存直接设置显示字符
mov [0xb8000+esi],cl
mov [0xb8001+esi],dl
inc dl
inc esi
inc esi
inc cl
cmp si,10000
je end_show
jmp show
end_show:
jmp $
编译为:
nasm -o boot.bin boot.asm
nasm -o setup.bin setup.asm
nasm -o set.bin set.asm
运行的时候可以使用软盘映像,你可以使用C语言创建一个1.44MB的二进制文件,里面可以直接全部写0,然后下面程序可以写入:
write.c:
#include<stdio.h>
#include<stdlib.h>
int main()
{
FILE *fp=NULL;
FILE *fp1=NULL;
char s[100];
char s1[100];
char c;
int mark=0;
long pos;
printf("please enter the name of file:");
scanf("%s",s);
fp=fopen(s,"rb");
if(NULL==fp)
{
printf("Have no such file!\n");
return 0;
}
printf("please enter the image file name:");
scanf("%s",s1);
fp1=fopen(s1,"rb+");
if(NULL==fp1)
{
printf("Have no such file!\n");
return 0;
}
printf("please input the position of the file you want to write:");
scanf("%ld",&pos);
fseek(fp1,pos,0);
while(!feof(fp))
{
if(mark)
{
fputc(c,fp1);
// printf("%x ",c);
}
c=fgetc(fp);
mark=1;
}
c=240;
fputc(c,fp1);
c=255;
fputc(c,fp1);
fputc(c,fp1);
fclose(fp);
fclose(fp1);
printf("write ok!\n");
system("pause");
return 0;
}
程序使用bochs调试,关于bochs可以直接去百度搜,也可以直接使用虚拟机运行img文件。
编译一下:gcc write.c(在windows下使用MinGW的gcc编译)
可以使用批处理来编译等。比如我的汇编源程序保存在F:\huibian\Diers里面,而write.c保存在桌面上OS test\imagewriter里面,里面还有Diers.img软盘映像文件,里面还有文件如下:
in1.txt:
boot.bin
Diers.img
0
in2.txt:
setup.bin
Diers.img
512
in3.txt:
set.bin
Diers.img
1536
我的bochs调试文件放在桌面上OS test\bochs里面,里面还放了一个set.bat批处理文件,内容如下:
F:
cd huibian\Diers
nasm -o boot.bin boot.asm
nasm -o setup.bin setup.asm
nasm -o set.bin set.asm
xcopy boot.bin C:\Users\Administrator\Desktop"OS test"\imagewriter\boot.bin /Y
xcopy setup.bin C:\Users\Administrator\Desktop"OS test"\imagewriter\setup.bin /Y
xcopy set.bin C:\Users\Administrator\Desktop"OS test"\imagewriter\set.bin /Y
C:
cd C:\Users\Administrator\Desktop"OS test"\imagewriter
a.exe <in1.txt
a.exe <in2.txt
a.exe <in3.txt
xcopy Diers.img C:\Users\Administrator\Desktop"OS test"\bochs\Diers.img /Y
Pause
需要调试运行的时候直接双击set.bat文件,会在bochs文件夹出现Diers.img文件,使用bochs运行或者使用虚拟机运行都可。
运行效果图:
参考文献:
《操作系统引导探究》(Version 0.02) 谢煜波
《Linux内核完全注释》修正版V1.9.5 赵炯
《Linux0.11源码分析》Version0.1 潘晓雷
《自己动手写操作系统》 于渊 编著, 尤晋元 审校
《微机原理与接口技术》第2版 周明德 主编,周明德、蒋本珊 著
《汇编语言程序设计》 齐志儒、高福祥 主编
百度空间:http://hi.baidu.com/yvoilee/blog/item/901476ee40a7a12badafd5e3.html
文章更正篇:http://blog.sina.com.cn/s/blog_6730a3aa01010xrc.html
操作系统引导--从实模式到保护模式相关推荐
- 操作系统学习:实模式进入保护模式
本文参考书籍 1.操作系统真相还原 2.Linux内核完全剖析:基于0.12内核 3.x86汇编语言 从实模式到保护模式 ps:基于x86硬件的pc系统 保护模式相关介绍 从实模式进入保护模式其实经历 ...
- x86从实模式到保护模式 pdf_【自制操作系统04】从实模式到保护模式
通过前三章的努力,我们成功将控制权转交给了 loader.asm 这个程序.具体说就是 bios 通过加载并跳转到 0x7c00(IMB大叔们定的) 把控制权转交给了我们操作系统的第一个汇编程序 mb ...
- 3.操作系统——CPU的实模式、保护模式和长模式
有实模式.保护模式.长模式 实模式16(实地址模式) 真实分为两个方面: 运行真实指令.不区分指令动作,只是直接执行指令的真实功能 发往内存的地址是真实.不加限制的. 总结来说就是,这个模式下直接往物 ...
- (操作系统开发)从实模式---->保护模式---->IA-32e模式( 64位模式)
实模式和保护模式都是CPU的工作模式. 实模式与保护模式介绍 在实模式下,程序可以操作任何地址空间,而且无法限制程序的执行权限.尽管这种模式给设置硬件功能带来许多方便,但却给程序执行的安全性和稳定性带 ...
- 【操作系统 3.了解实模式与保护模式的区别】
一.实模式与保护模式鸟瞰 我这人喜欢直面问题,其实本章只需要搞明白三个主要问题就行了, 什么是实模式和保护模式, 实模式与保护模式的区别是什么, 怎么进入保护模式. 我先来简单阐述下这三个问题 什么是 ...
- 操作系统:浅谈实模式,保护模式与长模式
学习了操作系统的实模式.保护模式与长模式,此文作为回顾. x86 CPU 在第一次加电和每次 reset 后,都会自动进入实模式,要想进入保护模式,就需要程序员写代码实现从实模式切换到保护模式. 一. ...
- 【OS修炼指南目录】----《X86汇编语言-从实模式到保护模式》读书笔记目录表
学习交流加(可免费帮忙下载CSDN资源): 个人微信: liu1126137994 学习交流资源分享qq群1(已满): 962535112 学习交流资源分享qq群2: 780902027 本文是将个人 ...
- Linux文件解hgc,Linux从实模式到保护模式.pdf
Linux从实模式到保护模式 Linux 内核源码学习 (1)- 从实模式到保护模式 notishell 发布于 3 年前 在查找资料的过程发现了一份关于 linux 内核启动的课件,在这里附上.(本 ...
- 深入理解计算机系统-之-内存寻址(二)--存储保护机制(CPU实模式与保护模式)
cpu的保护模式由来 分段机制 8086的诞生,标志着Intel 正式进入了x86时代,这是个多么具有纪念意义的日子:1978-6-8.同时,8086的诞生也是处理器内存寻址技术的第一次飞跃. 对于一 ...
最新文章
- IJCAI 2019精选论文一览,从底层到应用都有了
- 图像的大小计算 位深和色深
- AI赌神升级!无惧bluff,6人局德扑完胜世界冠军,训练只用了8天
- spring bean 小记
- Java String类型转换成Date日期类型
- 只用一套解决方案,就可解决80%的交通物流行业信息难题
- mac json工具_工具类封装的思路 | 钉钉群机器人为例
- Spring 事务传播原理及数据库事务操作原理
- BZOJ 2679 [Usaco2012 Open]Balanced Cow Subsets
- 跳出框架iframe的操作语句
- 轻松学习分布式|系列2|负载均衡算法。
- 深度学习之图像分类(七)--ResNet网络结构
- linux下addr2line详解
- shell之BASH_SOURCE
- 两条纵坐标折线图绘制
- 【css】i标签icon图标旋转样式
- 在外行人眼中的程序员
- 手牵手教你写 Vue 插件
- CSS3餐厅酒店网站模板是一款基于HTML5+CSS3实现的酒店预订模板下载。
- 【ArcGIS微课1000例】0055:根据图层创建自定义图例符号案例教程
热门文章
- hdu4115 2sat 石头剪刀布
- 【错误记录】Ubuntu 安装软件报错 ( Could not get lock /var/lib/dpkg/lock-frontend - open (11: Resource tempora )
- 【Groovy】Groovy 脚本调用 ( Java 类中调用 Groovy 脚本 )
- 【Android 应用开发】Activity 返回堆栈管理 ( 栈内复用模式 singleTask | 单实例模式 singleInstance )
- 【Android 应用开发】Android 返回堆栈管理 ( 默认启动模式 | 栈顶复用启动模式 | 栈内复用启动模式 | 单实例启动模式 | CLEAR_TOP 标识 )
- 基于SignalR的消息推送与二维码描登录实现
- .NET泛型解析(上)
- ODBC连接到400
- 使用Nginx的proxy_cache缓存功能取代Squid[原创]
- x86标志位符号表示(PF奇偶位)