qq老是进入保护模式式

保护模式FAQ
1.&Q:什么是保护模式?
A:保护模式是由电魂公司研发推出的一种账号安全保护系统。账号若处于保护模式中无法操作丢弃、购买、强化、分解、寄售等可能造成财产损失的敏感行为。
2.&Q:为什么会进入保护模式?
A:当您的帐号被系统检测到存在安全风险,系统即会将账号列入到保护模式进行保护,使您的帐号不受财产损失。
安全风险是指哪些风险? 会是密码泄露风险,盗号风险等。
3.&Q:保护模式下在游戏中我能做些什么?
A:进入保护模式的用户在保护模式解除之前只能进行:登录、移动、竞技、关卡、聊天等非敏感操作。
4.&Q:保护模式下在游戏中我不能做什么?
A:无法操作丢弃 、购买、强化、分解、寄售等可能造成财产损失的敏感行为。
保护模式图示:
保护模式图示:
5.&Q:保护模式如何解除?
A:保护模式脱出有两种方式:
1、 您可以通过绑定(免费)、实体统军令,即时解除保护模式。
2、自然解除。安全保护系统会根据您账号的风险情况,给出您保护模式时间长度,待保护时间结束,即可退出保护模式。
6.&Q:我的电脑没有查出病毒,为什么还是说有安全风险需要我查杀木马和修改密码?
A:较新的盗号木马,杀毒软件能检测到查杀会需要一定的时间。所以建议您每天更新杀软的病毒库并进行检测查杀,并同时在安全的机器上修改您的登陆密码。
7.&Q:是否所有账号都会进入保护模式?
A:不会,只有存在安全风险的账号,才会进入保护模式,正常情况下您的帐号不会进入安全模式。
8.&Q:如何防止账号被盗?
1)个人电脑,请一定要注意电脑系统的更新,及时修补系统存在的漏洞。安装正版杀软件,病毒防火墙,木马防火墙,不要上不明网站,木马是您帐号密码被盗的罪魁祸首之一,您需要时刻小心堤防
2、不要随便接收他人发来的的不知情的执行文件在不能确保其安全的情况下,不要随便接运行。
3、不要相信任何在游戏中私聊传播的中奖信息,一些活动请参考梦三国官网、梦塔防官网/
4、对于网吧用户,请尽量选择大型正规,管理措施相对完善的网吧,同时在上机前重启电脑或者进行安全扫描检查,输入密码时避免他人偷窥剽窃,在离开网吧时,也应该检查您是否已完全退出游戏。
9.&Q:动态密码正确,登陆却提示动密错误?
A:可能是由于电魂手机统军令时间漂移导致,打开电魂手机统军令APP,点击校准时间即可解决。《x86汇编语言:从实模式到保护模式》学习笔记(53)
之前已经做了一些理论上的铺垫,这次我们就可以看代码了。
一、代码清单
代码清单11-1
;文件名:c11_mbr.asm
;文件说明:硬盘主引导扇区代码
;创建日期: 19:54
;设置堆栈段和栈指针
mov sp,0x7c00
;计算GDT所在的逻辑段地址
mov ax,[cs:gdt_base+0x7c00]
mov dx,[cs:gdt_base+0x7c00+0x02]
mov bx,<span style="color:#
;令DS指向该段以进行操作
;段内起始偏移地址
;创建0#描述符,它是空描述符,这是处理器的要求
mov dword [bx&#43;0x00],0x00
mov dword [bx&#43;0x04],0x00
;创建#1描述符,保护模式下的代码段描述符
mov dword [bx&#43;0x08],0x7c0001ff
mov dword [bx&#43;0x0c],0x
;创建#2描述符,保护模式下的数据段描述符(文本模式下的显示缓冲区)
mov dword [bx&#43;0x10],0x8000ffff
mov dword [bx&#43;0x14],0x0040920b
;创建#3描述符,保护模式下的堆栈段描述符
mov dword [bx&#43;0x18],0x00007a00
mov dword [bx&#43;0x1c],0x
;初始化描述符表寄存器GDTR
mov word [cs: gdt_size&#43;0x7c00],<span style="color:#
;描述符表的界限(总字节数减一)
lgdt [cs: gdt_size&#43;0x7c00]
in al,0x92
;南桥芯片内的端口
out 0x92,al
;保护模式下中断机制尚未建立,应
mov eax,cr0
or eax,<span style="color:#
mov cr0,eax
;以下进入保护模式... ...
jmp dword 0x0008:flush
;<span style="color:#位的描述符选择子:32位偏移
;清流水线并串行化处理器
[bits <span style="color:#]
mov cx,_10_000B
;加载数据段选择子(0x10)
;以下在屏幕上显示&Protect mode OK.&
mov byte [0x00],'P'
mov byte [0x02],'r'
mov byte [0x04],'o'
mov byte [0x06],'t'
mov byte [0x08],'e'
mov byte [0x0a],'c'
mov byte [0x0c],'t'
mov byte [0x0e],' '
mov byte [0x10],'m'
mov byte [0x12],'o'
mov byte [0x14],'d'
mov byte [0x16],'e'
mov byte [0x18],' '
mov byte [0x1a],'O'
mov byte [0x1c],'K'
;以下用简单的示例来帮助阐述32位保护模式下的堆栈操作
mov cx,_11_000B
;加载堆栈段选择子
mov esp,0x7c00
mov ebp,esp
;保存堆栈指针
push byte '.'
;压入立即数(字节)
sub ebp,<span style="color:#
cmp ebp,esp
;判断压入立即数时,ESP是否减4
mov [0x1e],al
;已经禁止中断,将不会被唤醒
;-------------------------------------------------------------------------------
dw <span style="color:#
dd 0x00007e00
;GDT的物理地址
times <span style="color:#0-($-$$) db <span style="color:#
db 0x55,0xaa
上面就是配书源码。我们一点一点看。
二、源码分析
(一)设置堆栈和栈指针
;设置堆栈段和栈指针
mov sp,0x7c00
这个没有什么好说的,就是初始化栈。这三行执行后,SS=0; SP=0x7c00;
需要注意的是,这样设置后,栈的区域从0x向下扩展(不含0x这个字节),该区域包含了很多BIOS数据,包括实模式下的中断向量表,所以一定要小心。
(二)安装段描述符
;计算GDT所在的逻辑段地址
mov ax,[cs:gdt_base&#43;0x7c00]
mov dx,[cs:gdt_base&#43;0x7c00&#43;0x02]
mov bx,<span style="color:#
;令DS指向该段以进行操作
;段内起始偏移地址
怎么理解这段代码呢?
首先,在代码清单的95、96行,有
dw <span style="color:#
dd 0x00007e00
;GDT的物理地址
作者在这里声明了标号gdt_base,还初始化了一个双字——0x; 作者的意图是从这个地方开始建立全局描述符表GDT。我们的程序就是一个引导扇区,占用了512(=0x200)字节。程序加载的物理地址是0x7c00, 0x7c00&#43;0x200 = 0x7e00. 可见,在物理地址的安排上,引导程序后面紧跟着就是GDT。
目前我们还是处在实模式下,所以要建立GDT,必须将GDT的线性地址(物理地址)转换成实模式下使用的“段地址:偏移地址”的形式。
mov ax,[cs:gdt_base&#43;0x7c00] ;
这句使了段超越前缀“cs”,表明访问代码段中的数据;因为CS=0,所以就把物理地址(0x7c00&#43;gdt_base)处的0x7e00传送给了 同样地,将0x0000传送给 为了把线性地址转换成逻辑地址,我们用DX:AX除以16,得到的商(AX)就是段地址,余数(DX)就是偏移地址。
mov bx,16&&&&&&&
&&&&&&& div bx&&&&&&&&&&&
&&&&&&& mov ds,ax&&&&&&&&&&&&&&&&&&&&&&&&& ;令DS指向该段以进行操作
&&&&&&& mov bx,dx&&&&&&&&&&&&&&&&&&&&&&&&& ;段内起始偏移地址
这几行执行之后,GDT的逻辑地址就是 DS:BX.
;创建0#描述符,它是空描述符,这是处理器的要求
mov dword [bx&#43;0x00],0x00
mov dword [bx&#43;0x04],0x00
处理器规定,GDT中的第一个描述符必须是空描述符。这是什么原因呢?因为很多时候,寄存器和内存单元的初始&#20540;都会为0,再加上程序设计有问题,就会在无意中用全0的索引来选择描述符,这当然是不好的。因此,处理器要求将第一个描述符定义成空描述符。所以,上面两行代码定义了一个空描述符。
;创建#1描述符,保护模式下的代码段描述符
mov dword [bx&#43;0x08],0x7c0001ff
mov dword [bx&#43;0x0c],0x
这两行用来创建第二个描述符。之前的博文我们已经掌握了数据段和代码段描述符的&#26684;式,所以对这个描述符就不难理解了。
还记得我上一篇博文中写了一个小程序吗?
赶紧用它来分析一下吧:
线性基地址:0x
段界限为0x001FF,因为G=0,所以该段的长度是512(2的9次方)字节;
其他字段就不逐个说明了,相信你一定能懂。很明显,这个描述符定义的段,就是主引导程序所在的区域。
接着看代码。
;创建#2描述符,保护模式下的数据段描述符(文本模式下的显示缓冲区)
mov dword [bx&#43;0x10],0x8000ffff
mov dword [bx&#43;0x14],0x0040920b
程序分析的结果是:
seg_base = 0XB8000
seg_limit = 0XFFFF
数据段: 可读可写
看来这个段是指向显存的。
;创建#3描述符,保护模式下的堆栈段描述符
mov dword [bx&#43;0x18],0x00007a00
mov dword [bx&#43;0x1c],0x
这是创建栈段的描述符。程序分析的结果是:
-----------------------
seg_base = 0
seg_limit = 0X7A00
数据段: 向下扩展,可读可写
------------------------
正如作者所说:段界限的&#a00加上1(0x7a01),就是ESP寄存器所允许的最小&#20540;。当执行隐式的栈操作(如PUSH、CALL)时,处理器会检查ESP的&#20540;,一旦发现它小于0x7a01,就会引发异常中断。如果你还不理解,那么可以把书翻到215页。作者说在栈操作时,必须符合以下规则:
实际使用的段界限&#43;1 &= (ESP的内容减操作数的长度) &= 0xFFFF_FFFF
就拿这个例子来说,因为G=0,所以段界限就是0x7a00. 假设现在ESP的内容是0x7a04,此时执行下面的指令:
因为压入的是双字,所以处理器会先将ESP的&#20540;减去4,于是ESP=0x7a00. 因为0x7a00小于0x7a01,因此会引发异常中断。
(三)LGDT指令
好了,现在描述符已经安装完毕,接下来的工作是加载描述符表的线性基地址和界限到GDTR寄存器。相关的指令是lgdt. 该指令的&#26684;式为:
也就是说,该指令的操作数内存操作数。注意,该指令在实模式和保护模式下都可以执行,也不影响任何标志位。
这个内存操作数指向一个6字节的内存区域,要求低16位是GDT的界限&#20540;(表的总字节数减去1),高32位是GDT的线性基地址。
dw <span style="color:#
dd 0x00007e00
;GDT的物理地址
还记得吗,这是代码中事先定义了6字节的空间。前两个字节就是为了保存GDT的界限&#20540;。
;初始化描述符表寄存器GDTR
mov word [cs: gdt_size&#43;0x7c00],<span style="color:#
;描述符表的界限(总字节数减一)
lgdt [cs: gdt_size&#43;0x7c00]
第一句写入界限&#20540;,第二句把6字节加载到GDTR寄存器。
注意,到目前为止,我们依然在实模式下。
(四)关于A20
1.A20 GATE 起源[1]
在中,只有20根地址线,所以可以访问的地址是2^20=1M。但由于是16位地址模式,能够表示的地址范围是0-64K,所以为了访问1M内存,Intel采取了分段的模式。
即:物理地址=16位段地址*16 &#43; 16位偏移
但这种方式引起了新的问题,通过上述分段模式,能够表示的最大内存为:FFFFh:FFFFh=FFFF0h&#43;FFFFh=10FFEFh
但只有20位地址线,所以当访问FFEFh之间的内存时,系统并不认为访问越界而产生异常,而是自动从重新0开始计算,也就是说系统计算实际地址的时候是按照对1M求模的方式进行的,这种技术被称为wrap-around(回绕)。
到了80286,系统的地址总线发展为24根,这样能够访问的内存可以达到2^24=16M。为了兼容,Intel在设计80286时提出的目标是:在实模式下,系统所表现的行为应该和所表现的完全一样。但最终,80286芯片却存在一个BUG:如果程序员访问FFEFH之间的内存,系统将实际访问这块内存,而不是象过去一样重新从0开始。
为了解决上述问题,IBM使用键盘控制器上剩余的一些输出线来管理第21根地址线(从0开始数是第20根),被称为A20Gate;如果A20 Gate打开,则当程序员给出FFEFH之间的地址的时候,系统将真正访问这块内存区域;如果A20Gate被禁止,则当程序员给出FFEFH之间的地址的时候,系统仍然使用的方式。绝大多数IBM PC兼容机默认的A20Gate是被禁止的。由于在当时没有更好的方法来解决这个问题,所以IBM使用了键盘控制器来操作A20 Gate,但是这种操作太麻烦了,要使用一大堆指令。
2.Alt_A20_GATE
Alt_A20_GATE ,又称Fast A20. 通过端口0x92的bit1来打开A20,具体方法是:先从端口读出原数据,接着将bit1置1,然后再写入该端口,这样就打开了A20.
正如代码所示
in al,0x92
;南桥芯片内的端口
out 0x92,al
一次学太多会不会觉得累呢?我们就说到这里,下次继续…
【参考资料】
[1] 如烟海的专栏.
参考知识库
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:40577次
积分:1369
积分:1369
排名:千里之外
原创:98篇
评论:27条
文章:39篇
阅读:20447
(2)(5)(4)(11)(8)(14)(2)(17)(4)(3)(2)(8)(1)(1)(2)(6)(4)(3)(2)(1)下次自动登录
现在的位置:
& 综合 & 正文
实现OS中BOOTLOADER过程,并进入保护模式的代码
;;;;;;;实现进入进入保护模式,简单实现gdt,还没实现idt,用fat格式,这样利于内核文件的扩展。编写好内核之后,
;;;;;;;;可以直接放到软盘的根目录下。不需要在用镜像文件写入磁盘。
;;;;;;;;内存分配,堆栈在8FFFF,内核在500H,目录文件名被读取到7E00,等待扩展保护模式中断,完善磁盘读文件过程
[org 0x7c00] ; 告诉编译器加载到7c00处
CATALOG equ 0x7E00catalog loaded at 0x7e00
equ 0x500kernel.bin loaded at 0x500.
; 引导区文件系统数据
;----------------------------------------------------------------------------
DB " T's OS " 0003h - 引导程序的名字
DW 0x200 000Bh - 每扇区的字节数 512
DB 0x01 000Dh - 每簇扇区数
brResCount
0xEh - 保留扇区数
DB 0x02 0010h - FAT 备份数
brRootEntries
0x00e0 0011h - 根目录文件数
brSectorCount
DW h - 磁盘容量扇区数& 32MB
DB 240 0015h - 媒体描述符
DW 9 0016h - 每FAT扇区数
DW 18 0018h - 每磁道扇区数
DW 2 001Ah - 盘面数
DD 0 001Ch - 隐藏扇区数
DD 0 0020h - 如果大于32m的扇区总数
DB 0 0024h - 物理驱动器号
DB 0 0025h - 系统保留
DB 29H 0026h - 扩展扇区标记(包含29h)
brSerialNum DD
27h - 卷ID
' 002Bh - 卷标
' 0036h - 系统保留
;------------------------------------------------------------------------
mov ax, cs
mov ds, ax
mov es, ax
mov ax,0x8000栈放在0x1F00段里,这里栈有问题(栈放在0x1F00段里,会覆盖掉中断程序。)!!!!!!!!!!!!!!!
mov sp,0 堆栈入口 8FFFF
call DispS 调用显示字符串例程
call LoadF 把目录区读入到200的地方,bios
call FindF 在7E00的地方找kernel.bin,读出来放到500的地方,并显示读取成功
call C先清屏
;=============================================
;SwitchPro建立GDT,进入保护模式
;=============================================
in al, 92h
out 92h, al
end 打开A20
mov ax,KERNEL lgdt 指令加载 gdtr 是以ds为数据段加载
lea si, [dword gdtr]
lgdt [gdtr]
lea si, [dword idtr]
lidt [dword gdtr]
mov eax, cr0
mov cr0, eax
jmp dword selcode:0进入保护模式,并且跳到下面的段中
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;jmp KERNEL
保护模式下,跳到kenel.bin开始执行内核.等待内核编码完成在实现
mov eax,codesel_gdt
mov ebx,datasel_gdt
mov ax,ProMessage
mov cx,ProMsglength
PrintM保护模式中断有问题,需要修改这里,最好能利用实模式下的bios中断程序。
;===================
mov ax, 初始化gs,使其指向显示内存
mov word [gs:0],0x741 ; 在保护模式下显示一个白色的字符A
;===================
jmp $ 到此停止!!!!!!!!!!!!!!!!!!!!!!!
;===================================================================
;初始化gdtr和gdt
;===================================================================
dw gdt_end - gdt-1 gdt的长度--16位(800H)GDT界限gdt limit= GDT entries
这里应该是伪长度7,15,23,31,因为从0开始计算的
gdt的物理地址--32位GDT基地址
0x!!!!!!!!
dw 0,0,0,0
codesel_gdt:
界限Limit值 = 0x100000 * 0x1000 = 4GB
CODE32;0x0000
基地址 = CODE32.!!!!!!!是不是最好设置从0开始?
表示 存在 可执行可读段
粒度以及32位代码1100=0XC
datasel_gdt:
表示 存在 可读写数据段
粒度以及数据锻大小4G,1100=0XC
;========================
videosel equ $-gdt
dw 0x8000 ; 基址是0xb8000
;========================
selcode equ codesel_gdt -索引值1,2,3....
seldata equ datasel_gdt - gdt
;=============================================
;DispStr 显示boot已经启动!
;=============================================
mov ax, BootMessage
mov bp, es:bp = 串地址
mov cx, M cx = 串长度
call PrintMsg
;=============================================
;LoadFile 把目录从软盘中读出来!
;=============================================
mov ax,19开始的扇区
mov bx,CATALOG目录放在7E00H的地方!!!!!!!!!!!!!!!!!!!!!!!!!!!
mov cx,14目录扇区个数
loopreadsec:
LBACHS 调用转换
dl, 0 因为是a:所以为0!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
ah, 0x02 BIOS 读取扇区命令
al, 0x01 一个扇区
0x13 调用中断
add bx,200
loop loopreadsec
;=============================================
; 转换逻辑块访问为读取磁盘所使用的磁道,盘面,扇区
; 相对扇区 = (逻辑扇区 / 每磁道扇区数) + 1
; 相对盘面
= (逻辑扇区 / 每磁道扇区数) MOD 盘面数
; 相对磁道 = 逻辑扇区 / (每磁道扇区数 * 盘面数)
;=============================================
dx, dx = 0
div: ax/18 -& 商:ax 余数:dx
dx, dx = 0
ax/2 -& 商:ax 余数:dx
;=============================================
;FindFile 查找文件名,并且装到0x500,显示Load Kernel.bin Success!
;=============================================
地址自动增加
mov cx,224
根目录共有224个文件
mov di,CATALOG
目录放在7E00H的地方!!!!!!!!!!!!!!!!!!!!!
.l_findfile:
lea si,[Kernel]
8+3=0xb文件名和后缀长度
repe cmpsb
je findfile_ok
开始找下1个文件
loop .l_findfile
mov ax, LoadKerFail 失败
mov bp, ax
es:bp = 串地址
mov cx, LoadKerFaillengt cx = 串长度
call PrintMsg
findfile_ok:
add di,26取文件占用的第一个簇号,即起始簇
mov ax,[di]
add ax,31簇转成扇区
mov bx,KERNEL
文件放在0x500!!!!!!!!!!!!!!!!!!!!!!!!!!!
LBACHS 调用转换
dl, 0 因为是a:所以为0!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
ah, 0x02 BIOS 读取扇区命令
一个扇区,这里不应该只读一个扇区,应该根据文件大小来决定,等待修改!!!!!
0x13 调用中断,内核放在0x1e00!在磁盘的位置?
mov ax, LoadKerSuess
mov bp, ax
es:bp = 串地址
mov cx, LoadKerlength
cx = 串长度
call PrintMsg
;=============================================
;=============================================
mov ax,0x0600 ; 使用中断10h的功能6,实现卷屏,如果al=0则清屏
mov cx,0x0000 ; 清屏
mov dx,0x174 卷屏至23,79
mov bh,0 ; 使用颜色0来填充
int 0x10 ; 调用10h中断
;=============================================
;=============================================
mov ax, 01301 ah = 13, al = 01h
mov bx, 000 页号为0(bh = 0) 黑底红字(bl = 0Ch,高亮)
mov dh, BYTE [NoLine]
int 10 10h 号中断
mov BYTE [NoLine],dh
BootMessage: db "Welcome to T's OS!",0x0D,0x0A
Msglength equ $-BootMessage
Kernel: db 'KERNEL
BIN'8+3=11位;将来这里改成内核的文件名!!!!!!!!!!!!!
LoadKerSuess: db 'Load Kernel.bin Success!',0x0D,0x0A
LoadKerlength equ $-LoadKerSuess
LoadKerFail: db 'Load Kernel.bin Fail!',0x0D,0x0A
LoadKerFaillength equ $-LoadKerFail
ProMessage: db "I'm in the Pro Mode!",0x0D,0x0A
ProMsglength equ $-ProMessage
NoLine DB 0x00
times 510-($-$$) db 0 ; 填充剩下的空间,使生成的二进制代码恰好为512字节
dw 0xaa55 ; 结束标志
;把这段代码用NASM编译一下:
;nasm boot.asm –o boot.bin
;应该把内核在pro模式下加载就对了!
&&&&推荐文章:
【上篇】【下篇】解救,从这里开始
*不能登录的帐号:}

我要回帖

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

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信