冻结 qq老是保护模式式吗

如何进入保护模式
& & 这是个复杂的过程,其原因在于保护模式本身是复杂的。
& & 相对于8086来说,386增加了很多新寄存器,用于支持多任务操作系统,或者说让CPU能工作在保护模式下。CR0就是其中之一。CR指Control Register,控制寄存器。CR0是CR中的一个。CR的最后一个bit是PE位,Protected-mode Enable,保护模式使能位。386开机后工作在实模式,可以通过16位指令置CR0的最后一个bit为1,从此CPU进入保护模式。
& & set PE操作虽然能让CPU进入保护模式,但这并不意味着进入保护模式的CPU可以正常工作。这是因为相对于实模式下的CPU,保护模式下的CPU需要依赖一些特殊的数据结构才能正常工作,除此之外,很多琐碎的问题也需要考虑在内。
& & 首先,为了给存储器内的段提供独立性,386引入了一个数据结构GDT,Global Descriptor Table。386有32位的寄存器,32根地址线,不在依靠分段机制访问“超过寄存器长度的存储器地址(指段地址:偏移的寻址方式)”,但是出于兼容性与内存管理等方面的考虑,段的概念依然被保留在了386内。此时,段机制的意义只在与将存储器分割成了更小的部分。为了让这些段具有独立性,Intel引入了GDT,保存各个段在存储器中的位置与和段隔离有关的信息。该表可以很大,保存在RAM中,而386通过GDTR(GDT
Register),一个32(base address) + 16(boundary)= 48位的寄存器,定位GDT的位置。从寄存上看,GDT可以存在于4GB RAM的任何位置,但实模式下,386只能寻址1MB。因此GDT往往在RAM的第一个1MB内。GDT是一个数据结构,存储为保证段独立性而必须的信息。换句话说,GDT保存了对段的描述,而且是一个非常细致的描述。保护模式下,CPU内的段寄存器不再保存段地址,而是保存索引号(index),指向GDT中的描述信息。“段寄存器改变”对于CPU来说,隐含有操作“将段寄存器指向的段描述信息读入该段寄存器对应的描述符高速缓存”。从此,我们可以根据描述信息访问内存中的段。GDT表中的一个条目长64个bit,含有以下信息:
& & & & & & & & & &1. 32bit基地址与20bit界限,用以标明该段在内存中的位置和大小。说到这儿,我想起了...见ps2
& & & & & & & & & &2. G,Granularity,粒度,也就是段界限的单位,有byte和4KB两种,前者对应最大1MB的段,后者对应最大4GB的段。
& & & & & & & & & &3. 描述信息
& & & & & & & & & & & & S,Descriptor Type,描述符类型;
& & & & & & & & & & & & DPL,Descriptor Privilege Level,描述符特权级;
& & & & & & & & & & & & P,Segment Present,段存在位;
& & & & & & & & & & & & D/B,Default Operation Size/Default Stack Pointer Size,默认操作数大小/默认堆栈指针大小; &
& & & & & & & & & & & & L,64-bit Code Segment,保留给64-bit 处理器使用。
& & & & & & & & & & & & TYPE,用以描述段属性。代码段和数据段共有的属性是可运行性(X,eXcutable)和最近已访问性(A,Access),对于代码段,X一定是1,而数据段的X一定为0;A在该段被访问时会被set,向操作系统提 & & & & & & & & & & & & & & 供内存管理的依据。数据段另有两个属性,扩展方向(E,ExtendDirection?)和可写性(W,Writable)。E和W略。代码段另有两个属性,特权已从(C,Conforming)和(R,Readable)。C和R略。
& & & & & & & & & & & & AVL(Avaible,随便使用的一个bit)
由上可知,相对于8086的简单的段寄存器,GDT给出了段的大小和位置,以及一套相当细致的描述信息。这些描述信息有两个作用:一是提供段和段之间的隔离;二是为操作系统进行内存管理提供依据。在进入保护模式之前,386必须初始化GDT,让GDTR指向GDT。
& & 第二,A20问题。A20问题来自于386对8086程序的支持。8086有20根地址线:A0-A19。很多8086程序利用了“地址回环”。所谓“地址回环”指当地址超过20根地址线所能表达的范围,即0xFFFFF,地址将回环到0x00000。因此,如果16位段地址很“靠后”,比如段地址为0xFFFF时,该段其实要“回环”到内存的头部。但是这些利用了“地址回环”的程序不能被386实模式兼容,因为386的地址线长达32位。如果出现了超过0xFFFFF地址,比如0x1 00000,这些地址超过20位的部分会被保留(在8086里会被舍弃)用来去寻址RAM——这和编写那些程序的程序员所期待的“地址回环”不同。初期的解决办法是利用外部芯片将A20强制清0。当然,为了让地址彻底“坍缩”成20位地址,似乎要将A21-A31全部清0,但是貌似不会出现那么高的地址,毕竟产生A21为1的地址,意味着寻址超过0x20
0000——即使段地址最大,取0xFFFF,该段的最高地址也不会超过0xFFFF*16+0xFFFF = 0x16 FFE9。因此将A20清0就够了。后期的解决方法是由处理器提供一个控制引脚A20M#,M指Mask,低电平有效。也就是低电平会让A20始终为0。ICH芯片的92端口的bit1可以用来控制A20M#,0对应低电平,也就是A20始终为0,1对应高电平,也就是启用A20。进入保护模式后,如果A20依然被屏蔽,会导致寻址“跳跃”。因此在进入保护模式前,必须通过92端口启用A20。
& & 第三,CLI。进入保护模式后,保护模式下的中断机制尚未建立而实模式的终端机制已经失效,因此进入PE位set之前,必须cli。
& & 第四,刷新段寄存器,清空流水线。set PE后,CPU进入保护模式。在CPU看来,段寄存器里的内容并没有变化,但是含义却从“段地址”变成了“段选择子”——这是个很严重的错误。因此,set PE后,应该立刻将段寄存器更新,而最紧迫的则是更新CS。因为CS会参与决定set PE后马上执行的指令是什么。另外,由于16位模式的386和32位模式的386对同样的机器码会有不同的理解(即译码结果不同,),因此流水线必须清空。解决上述两个问题的方法就是set PE后,马上执行一次远转移的jmp。jmp会更新CS,顺带更新CS的描述符高速缓存,同时清空流水线。这条指令应该是这个样子:jmp
index:offset,其中index作为段选择子指向本代码段。表面上看,因为这条指令在set PE之后,所以应该在32 bits模式下编译,进而得到如下的代码结构:
& & & & & &[bits 16]
& & & & & &....;LGDT,A20,CLI,SET PE
& & & & & &[bits 32]
& & & & & &jmp index:offset
& & & & & &...
但上述代码会发生错误。在[bits 32]关键字下,jmp index:offset被编译成EA |32bits of offset |16bits of index,而在[bits 16]关键字下,jmp index:offset被编译成EA |16bits of offset |16bits of index。前者会导致刚刚进入保护模式的CPU发生错误。首先,由于流水线的存在,译码单元以16bit模式译码机器码EA |32bits of offset |16bits of index,从而产生预料之外的jmp指令。CPU会将32bits
of offset的前16个bit作为offset赋给IP,后16bit作为index赋给CS——这和预想的完全不同。一个显而易见的纠正方法是采用如下结构的代码:
& & & & & &[bits 16]
& & & & & &....;LGDT,A20,CLI,SET PE
& & & & & &jmp index:offset & & & & &&
& & & & & &[bits 32]
& & & & & &...
在[bits 16]关键字下,jmp index:offset被编译成EA |16bits of offset |16bits of index。指令会导致CS被赋值16bits of index,CS的描述符高速缓冲被刷新,而EIP的后16bit后16bit后16bit后16bit被赋值16bits of offset...如果EIP的前16位为0的话,一切都会很顺利,但如果不是呢...妥善的解决办法是使用如下的代码:
& & & & & &[bits 16]
& & & & & &....;LGDT,A20,CLI,SET PE
& & & & & &jmp dword index:offset & & & & &&
& & & & & &[bits 32]
& & & & & &...
dword关键字告知编译器&使用32bit offset&,从而导致编译结果变成: 66 | EA | 32bits of offset| 16bits of index。0x66前缀将参与译码,提醒CPU将32bits of offset赋给EIP。这儿有些疑问,见PS1。
& & 终于进入保护模式了。
& & PS1: set PE后的第一条指令很“繁琐”。《x86汇编语言-从实模式到保护模式》一书中解释说:处理器刚刚进入保护模式,CS段的段描述符高速缓冲为全0,所以D/B位也为0,进而导致处理器对指令的操作依然采用16bit寄存器和16bit操作数——处理器在处理jmp时,工作在“16位保护模式”。但是,我怀疑这个解释的正确性。事实上,jmp操作的复杂性就在于这条指令&在16位模式下预取,在32位模式下执行&。预取的时候,处理器还没有进入32位模式,因此这条指令其实是在16位模式下进行的指令译码。在执行这条指令的时候,D/B位并没有起作用。我猜测D/B位参与的是流水线前期的工作,包括译码在内。总之,jmp指令执行时,我们必须认为处理器依然运行在16位模式,但是其原因究竟是D/B位在起作用,还是16位模式下对jmp的预取,我认为有待讨论。
& & PS2: winXP下用C++写程序,如果使用一个长达1MB的数组,比如char a[],程序运行时会发生错误。即使将数组拆分成两个,比如char a[512*1024],b[512*1024],也行不通。经过简单的测试可以发现,可以保证程序正常运行的数组的最大大小是一个接近1MB的值。发生这个事情的原因是否就是GDT条目中用20bit描述段界限呢?
&&相关文章推荐
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:4614次
排名:千里之外
原创:15篇
(4)(5)(4)(1)(1)我的QQ是别人送的,现在进去保护模式,怎么办。而且就连我自己的也经常被冻结_百度宝宝知道总是被人举报,冻结了怎么办要三天以后才可以解除保护模式怎么办
全部答案(共1个回答)
这个我也不会,问客服,他让打这个电话问问
@微女郎申请取消 。如果对您有帮助,请设置答案
有用 ,谢谢
首先登录我的支付宝账户,接着在右上角的帮助中心点击【自助服务】 。在所有自助服务框中的账户自助下点击【注销账户】。来到确认协议页面,直接点击【同意协议并继续】按...
由于目前微女郎正在建设之中,所以暂时无法实现线上申请取消。如果您确定要取消微女郎,请将您的取消原因和个人信息以私信的形式发送给@微女郎 帮您撤销。 点此-&ht...
没有取消选项 可以不用理会 一般没人处理 即使有人受理 看到是错误举报 不会在意的 [如果我的回答对您有帮助 请点击"好评"支持下 谢谢]
答: 后天照二维?有谁知道二维都检查什么
答: 慢慢弄。我最开始只会装游戏;后来中国有了网络慢慢跟朋友上聊天室聊天;后来出了OICQ(现在叫QQ),又用那东西聊;然后上联众玩在线游戏(棋牌类);后来乱七八糟逛...
答: 七十年代的计算机网络X.25 分组交换网:各国的电信部门建设运行各种专用的网络体系结构:SNA,DNAInternet 的前身ARPANET进行实验运行八十年代...
大家还关注
确定举报此问题
举报原因(必选):
广告或垃圾信息
激进时政或意识形态话题
不雅词句或人身攻击
侵犯他人隐私
其它违法和不良信息
报告,这不是个问题
报告原因(必选):
这不是个问题
这个问题分类似乎错了
这个不是我熟悉的地区QQ号被暂时冻结,解冻需要解除保护模式。可是有卵求的保护模式啊!? - 知乎0被浏览26分享邀请回答还没有回答

我要回帖

更多关于 qq号总是进入保护模式 的文章

 

随机推荐