现在的位置: 首页 > 综合 > 正文

实模式与保护模式

2013年02月12日 ⁄ 综合 ⁄ 共 10594字 ⁄ 字号 评论关闭

基础之概念 本应清晰,而我心知混混沌沌,故网摘几篇,作为笔记:

————————————————————————————————————————

80386处理器有3种工作模式:实模式、保护模式和虚拟86模式。实模式和虚拟86模式是为了和8086处理器兼容而设置的。在实模式下,80386处理器就相当于一个快速的8086处理器。保护模式是80386处理器的主要工作模式。在此方式下,80386可以寻址4   GB的地址空间,同时,保护模式提供了80386先进的多任务、内存分页管理和优先级保护等机制。为了在保护模式下继续提供和8086处理器的兼容,80386又设计了一种虚拟86模式,以便可以在保护模式的多任务条件下,有的任务运行32位程序,有的任务运行MS-DOS程序。在虚拟86模式下,同样支持任务切换、内存分页管理和优先级,但内存的寻址方式和8086相同,也是可以寻址1   MB的空间。

由此可见,80386处理器的3种工作模式各有特点且相互联系。实模式是80386处理器工作的基础,这时80386当做一个快速的8086处理器工作。在实模式下可以通过指令切换到保护模式,也可以从保护模式退回到实模式。虚拟86模式则以保护模式为基础,在保护模式和虚拟86模式之间可以互相切换,但不能从实模式直接进入虚拟86模式或从虚拟86模式直接退到实模式。

1.   实模式

80386处理器被复位或加电的时候以实模式启动。这时候处理器中的各寄存器以实模式的初始化值工作。80386处理器在实模式下的存储器寻址方式和8086是一样的,由段寄存器的内容乘以16当做基地址,加上段内的偏移地址形成最终的物理地址,这时候它的32位地址线只使用了低20位。在实模式下,80386处理器不能对内存进行分页管理,所以指令寻址的地址就是内存中实际的物理地址。在实模式下,所有的段都是可以读、写和执行的。

实模式下80386不支持优先级,所有的指令相当于工作在特权级(优先级0),所以它可以执行所有特权指令,包括读写控制寄存器CR0等。实际上,80386就是通过在实模式下初始化控制寄存器,GDTR,LDTR,IDTR与TR等管理寄存器以及页表,然后再通过加载CR0使其中的保护模式使能位置位而进入保护模式的。实模式下不支持硬件上的多任务切换。

实模式下的中断处理方式和8086处理器相同,也用中断向量表来定位中断服务程序地址。中断向量表的结构也和8086处理器一样,每4个字节组成一个中断向量,其中包括两个字节的段地址和两个字节的偏移地址。

从编程的角度看,除了可以访问80386新增的一些寄存器外,实模式的80386处理器和8086有什么进步呢?其实最大的好处是可以使用80386的32位寄存器,用32位的寄存器进行编程可以使计算程序更加简捷,加快了执行速度。比如在8086时代用16位寄存器来完成32位的乘法和除法时,要进行的步骤实在是太多了,于是考试时出这一类的题目就成了老师们的最爱,所以那时候当学生做梦都想着让寄存器的位数快快长,现在梦想终于成真了,用32位寄存器一条指令就可以完成(问题是老师们也发现了这个投机取巧的办法,为了达到让学生们基础扎实的目的,也把题目换成了64位的乘法和除法,所以现在晚上做的梦换成了寄存器忽然长到了64位);其次,80386中增加的两个辅助段寄存器FS和GS在实模式下也可以使用,这样,同时可以访问的段达到了6个而不必考虑重新装入的问题;最后,很多80386的新增指令也使一些原来不很方便的操作得以简化,如80386中可以使用下述指令进行数组访问:

        mov   cx,[eax   +   ebx   *   2   +   数组基地址]

这相当于把数组中下标为eax和ebx的项目放入cx中;ebx   *   2中的2可以是1,2,4或8,这样就可以支持8位到64位的数组。而在8086处理器中,实现相同的功能要进行一次乘法和两次加法。另外,pushad和popad指令可以一次把所有8个通用寄存器的值压入或从堆栈中弹出,比起用下面的指令分别将8个寄存器入栈要快了很多:

        push         eax

        push         ebx

        ...

        pop   ebx

        pop   eax

当然,使用了这些新指令的程序是无法拿回到8086处理器上去执行的,因为这些指令的编码在8086处理器上是未定义的。

2.   保护模式

当80386工作在保护模式下的时候,它的所有功能都是可用的。这时80386所有的32根地址线都可供寻址,物理寻址空间高达4   GB。在保护模式下,支持内存分页机制,提供了对虚拟内存的良好支持。虽然与8086可寻址的1   MB物理地址空间相比,80386可寻址的物理地址空间可谓很大,但实际的微机系统不可能安装如此大的物理内存。所以,为了运行大型程序和真正实现多任务,虚拟内存是一种必需的技术。

保护模式下80386支持多任务,可以依靠硬件仅在一条指令中实现任务切换。任务环境的保护工作是由处理器自动完成的。在保护模式下,80386处理器还支持优先级机制,不同的程序可以运行在不同的优先级上。优先级一共分0~3   4个级别,操作系统运行在最高的优先级0上,应用程序则运行在比较低的级别上;配合良好的检查机制后,既可以在任务间实现数据的安全共享也可以很好地隔离各个任务。从实模式切换到保护模式是通过修改控制寄存器CR0的控制位PE(位0)来实现的。在这之前还需要建立保护模式必需的一些数据表,如全局描述符表GDT和中断描述符表IDT等。

DOS操作系统运行于实模式下,而Windows操作系统运行于保护模式下。

3.   虚拟86模式

虚拟86模式是为了在保护模式下执行8086程序而设置的。虽然80386处理器已经提供了实模式来兼容8086程序,但这时8086程序实际上只是运行得快了一点,对CPU的资源还是独占的。在保护模式的多任务环境下运行这些程序时,它们中的很多指令和保护模式环境格格不入,如段寻址方式、对中断的处理和I/O操作的特权问题等。为了在保护模式下工作而丢弃这些程序的代价是巨大的。设想一下,如果Windows或80386处理器推出的时候宣布不能运行以前的MS-DOS程序,那么就等于放弃了一个巨大的软件库,Windows以及80386处理器可能就会落得和苹果机一样的下场,这是Microsoft和Intel都不愿看到的。所以,80386处理器又设计了一个虚拟86模式。

虚拟86模式是以任务形式在保护模式上执行的,在80386上可以同时支持由多个真正的80386任务和虚拟86模式构成的任务。在虚拟86模式下,80386支持任务切换和内存分页。在Windows操作系统中,有一部分程序专门用来管理虚拟86模式的任务,称为虚拟86管理程序。

既然虚拟86模式以保护模式为基础,它的工作方式实际上是实模式和保护模式的混合。为了和8086程序的寻址方式兼容,虚拟86模式采用和8086一样的寻址方式,即用段寄存器乘以16当做基址再配合偏移地址形成线性地址,寻址空间为1   MB。但显然多个虚拟86任务不能同时使用同一位置的1   MB地址空间,否则会引起冲突。操作系统利用分页机制将不同虚拟86任务的地址空间映射到不同的物理地址上去,这样每个虚拟86任务看起来都认为自己在使用0~1   MB的地址空间。

8086代码中有相当一部分指令在保护模式下属于特权指令,如屏蔽中断的cli和中断返回指令iret等。这些指令在8086程序中是合法的。如果不让这些指令执行,8086代码就无法工作。为了解决这个问题,虚拟86管理程序采用模拟的方法来完成这些指令。这些特权指令执行的时候引起了保护异常。虚拟86管理程序在异常处理程序中检查产生异常的指令,如果是中断指令,则从虚拟86任务的中断向量表中取出中断处理程序的入口地址,并将控制转移过去;如果是危及操作系统的指令,如cli等,则简单地忽略这些指令,在异常处理程序返回的时候直接返回到下一条指令。通过这些措施,8086程序既可以正常地运行下去,在执行这些指令的时候又觉察不到已经被虚拟86管理程序做了手脚。MS-DOS应用程序在     Windows操作系统中就是这样工作的。

 

——————————————————————————————————————————————————

 

什么是保护模式
自从1969年推出第一个微处理器以来,Intel处理器就在不断地更新换代,从8086、8088、80286,到80386、80486、奔腾、奔腾Ⅱ、奔腾4等,其体系结构也在不断变化。80386以后,提供了一些新的功能,弥补了8086的一些缺陷。这其中包括内存保护、多任务及使用640KB以上的内存等,并仍然保持和8086家族的兼容性。也就是说80386仍然具备了8086和80286的所有功能,但是在功能上有了很大的增强。早期的处理器是工作在实模式之下的,80286以后引入了保护模式,而在80386以后保护模式又进行了很大的改进。在80386中,保护模式为程序员提供了更好的保护,提供了更多的内存。事实上,保护模式的目的不是为了保护程序,而是要保护程序以外的所有程序(包括操作系统)。
简言之,保护模式是处理器的一种最自然的模式。在这种模式下,处理器的所有指令及体系结构的所有特色都是可用的,并且能够达到最高的性能。
保护模式和实模式
从表面上看,保护模式和实模式并没有太大的区别,二者都使用了内存段、中断和设备驱动来处理硬件,但二者有很多不同之处。我们知道,在实模式中内存被划分成段,每个段的大小为64KB,而这样的段地址可以用16位来表示。内存段的处理是通过和段寄存器相关联的内部机制来处理的,这些段寄存器(CS、DS、SS和ES)的内容形成了物理地址的一部分。具体来说,最终的物理地址是由16位的段地址和16位的段内偏移地址组成的。用公式表示为:
物理地址=左移4位的段地址+偏移地址。
在保护模式下,段是通过一系列被称之为"描述符表"的表所定义的。段寄存器存储的是指向这些表的指针。用于定义内存段的表有两种:全局描述符表(GDT)和局部描述符表(LDT)。GDT是一个段描述符数组,其中包含所有应用程序都可以使用的基本描述符。在实模式中,段长是固定的(为64KB),而在保护模式中,段长是可变的,其最大可达4GB。LDT也是段描述符的一个数组。与GDT不同,LDT是一个段,其中存放的是局部的、不需要全局共享的段描述符。每一个操作系统都必须定义一个GDT,而每一个正在运行的任务都会有一个相应的LDT。每一个描述符的长度是8个字节,格式如图3所示。当段寄存器被加载的时候,段基地址就会从相应的表入口获得。描述符的内容会被存储在一个程序员不可见的影像寄存器(shadow register)之中,以便下一次同一个段可以使用该信息而不用每次都到表中提取。物理地址由16位或者32位的偏移加上影像寄存器中的基址组成。实模式和保护模式的不同可以从图1和图2中很清楚地看出来。
此外,还有一个中断描述符表(IDT)。这些中断描述符会告诉处理器到那里可以找到中断处理程序。和实模式一样,每一个中断都有一个入口,但是这些入口的格式却完全不同。因为在切换到保护模式的过程中没有使用到IDT,所以在此就不多做介绍了。
进入保护模式
80386有4个32位控制寄存器,名字分别为CR0、CR1、CR2和CR3。CR1是保留在未来处理器中使用的,在80386中没有定义。CR0包含系统的控制标志,用于控制处理器的操作模式和状态。CR2和CR3是用于控制分页机制的。在此,我们关注的是CR0寄存器的PE位控制,它负责实模式和保护模式之间的切换。当PE=1时,说明处理器运行于保护模式之下,其采用的段机制和前面所述的相应内容对应。如果PE=0,那么处理器就工作在实模式之下。
切换到保护模式,实际就是把PE位置为1。为了把系统切换到保护模式,还要做一些其它的事情。程序必须要对系统的段寄存器和控制寄存器进行初始化。把PE位置1后,还要执行跳转指令。过程简述如下:
1.创建GDT表;
2.通过置PE位为1进入保护模式;
3.执行跳转以清除在实模式下读取的任何指令。
实模式下,cpu指令访问的地址就是物理地址,形式为:段寄存器:偏移
在保护模式下,cpu可以使用分段机制和分页机制。
分段机制下使用的地址就是逻辑地址,形式为:段选择子:偏移
分页机制下使用的地址就是线性地址,形式为:0xXXXXXXXX
无论是逻辑地址还是线性地址,都要被cpu映射成物理地址。
保护模式下必须采用分段机制。在此基础上可采用分页机制。
逻辑地址被转化为线性地址,如果采用分页机制,则该线性地址通过分页机制被映射成物理地址。如果不采用分页机制,则该线性地址就是物理地址。
实模式下的物理地址只能访问1M以下空间,而保护模式下的物理地址可以访问所有32位空间。并且要注意,物理内存空间只是物理地址空间的一个部分而已。

 

 

 

————————————————————————————————————————————————————————

首先说明实模式,虚拟模式,保护模式是X86中的概念。
       我从寻址方式来说,CPU的IP(EIP)中存放的是虚地址,把一个虚地址转换为物理地址,模式不同,转换方式不同:
       实模式下-虚地址到实地址转换,段寄存器左移四位与偏移相加,得到物理地址,寻址空间1M。
       保护模式下--虚地址到实地址转换经过MMU,也就是分段和分页机制(具体了解这个比较复杂,但其实也不难),寻址空间4G。另外,保护有两层含义,一是保护操作系统不被随意访问和破坏,另外,保护应用程序在各自的地址空间不被随意破坏。

    在微处理器的历史上,第一款微处理器芯片4004是由Intel推出的,那是一个4位的微处理器。在4004之后,intel推出了一款8位处理器8080,它有1个主累加器(寄存器A)和6个次累加器(寄存器B,C,D,E,H和L),几个次累加器可以配对(如组成BC, DE或HL)用来访问16位的内存地址,也就是说8080可访问到64K内的地址空间。另外,那时还没有段的概念,访问内存都要通过绝对地址,因此程序中的地址必须进行硬编码(给出具体地址),而且也难以重定位,这就不难理解为什么当时的软件大都是些可控性弱,结构简陋,数据处理量小的工控程序了。
    几年后,intel开发出了16位的处理器8086,这个处理器标志着Intel X86王朝的开始,这也是内存寻址的第一次飞跃。之所以说这是一次飞跃,是因为8086处理器引入了一个重要概念—段
    8086处理器的寻址目标是1M大的内存空间,于是它的地址总线扩展到了20位。但是,一个问题摆在了Intel设计人员面前,虽然地址总线宽度是20位的,但是CPU中“算术逻辑运算单元(ALU)”的宽度,即数据总线却只有16位,也就是可直接加以运算的指针长度是16位的。如何填补这个空隙呢?可能的解决方案有多种,例如,可以像一些8位CPU中那样,增设一些20位的指令专用于地址运算和操作,但是那样又会造成CPU内存结构的不均匀。又例如,当时的PDP-11小型机也是16位的,但是其内存管理单元(MMU)可以将16位的地址映射到24位的地址空间。受此启发,Intel设计了一种在当时看来不失为巧妙的方法,即分段的方法。
    为了支持分段,Intel在8086 CPU中设置了四个段寄存器:CS、DS、SS和ES,分别用于可执行代码段、数据段、堆栈段及其他段。每个段寄存器都是16位的,对应于地址总线中的高16位。每条“访内”指令中的内部地址也都是16位的,但是在送上地址总线之前,CPU内部自动地把它与某个段寄存器中的内容相加。因为段寄存器中的内容对应于20位地址总线中的高16位(也就是把段寄存器左移4位),所以相加时实际上是内存总线中的高12位与段寄存器中的16位相加,而低4位保留不变,这样就形成一个20位的实际地址,也就实现了从16位内存地址到20位实际地址的转换,或者叫“映射”。
段式内存管理带来了显而易见的优势,程序的地址不再需要硬编码了,调试错误也更容易定位了,更可贵的是支持更大的内存地址。程序员开始获得了自由。
    技术的发展不会就此止步。intel的80286处理器于1982年问世了,它的地址总线位数增加到了24位,因此可以访问到16M的内存空间。更重要的是从此开始引进了一个全新理念—保护模式。这种模式下内存段的访问受到了限制。访问内存时不能直接从段寄存器中获得段的起始地址了,而需要经过额外转换和检查。为了和过去兼容,80286内存寻址可以有两种方式,一种是先进的保护模式,另一种是老式的8086方式,被成为实模式。系统启动时处理器处于实模式,只能访问1M空间,经过处理可进入保护模式,访问空间扩大到16M,但是要想从保护模式返回到实模式,你只有重新启动机器。还有一个致命的缺陷是80286虽然扩大了访问空间,但是每个段的大小还是64k,程序规模仍受到限制。因此这个先天低能儿注定命不会很久。很快它就被天资卓越的兄弟——80386代替了。
    80386是一个32位的CPU,也就是它的ALU数据总线是32位的,同时它的地址总线与数据总线宽度一致,也是32位,因此,其寻址能力达到4GB。对于内存来说,似乎是足够了。从理论上说,当数据总线与地址总线宽度一致时,其CPU结构应该简洁明了。但是,80386无法做到这一点。作为X86产品系列的一员,80386必须维持那些段寄存器的存在,还必须支持实模式,同时又要能支持保护模式,这给Intel的设计人员带来很大的挑战。
    Intel选择了在段寄存器的基础上构筑保护模式,并且保留段寄存器16位。在保护模式下,它的段范围不再受限于64K,可以达到4G。这一下真正解放了软件工程师,他们不必再费尽心思去压缩程序规模,软件功能也因此迅速提升。
    从8086的16位到80386的32位处理器,这看起来是处理器位数的变化,但实质上是处理器体系结构的变化,从寻址方式上说,就是从“实模式”到“保护模式”的变化。从80386以后,Intel的CPU经历了80486、Pentium、PentiumII、PentiumIII等型号,虽然它们在速度上提高了好几个数量级,功能上也有不少改进,但基本上属于同一种系统结构的改进与加强,而无本质的变化,所以我们把80386以后的处理器统称为IA32(32 Bit Intel Architecture)。

 

本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/goodwinds/archive/2009/08/09/4429035.aspx

 

——————————————————————————————————————————————————————

 

 

 

实模式与保护模式

1. 实模式,又叫实地址模式,CPU完全按照8086的实际寻址方法访问从00000h--FFFFFh(1MB大小)的地址范围的内存,在这种模式下,CPU只能做单任务运行;寻址公式为:物理地址=左移4位的段地址+偏移地址,即:物理地址是由16位的段地址和16位的段内偏移地址组成的。
2.保护模式,又叫内存保护模式,寻址采用32位段和偏移量,最大寻址空间4GB,在这种模式下,系统运行于多任务,设计这种模式的原因和好处是:保护模式增加了寻址空间,增加了对多任务的支持,增加了段页式寻址机制的内存管理(分段机制使得段具有访问权限和特权级,各应用程序和操作系统的代码和核心是被保护的,这也是多任务支持的实现关键和保护这个名字的由来)。寻址过程为:物理地址=由段地址查询全局描述符表中给出的段基址+偏移地址,即:物理地址由影像寄存器中的基址加上16位或者32位的偏移组成。
 
 
 
 
 
 
 
 
 
 
 
 
1:实模式
是CPU启动的时候的模式
这时候就相当于一个速度超快的8086
不能使用多线程
不能实现权限分级
还不能访问20位以上地址线,也就是说只能访问1M内存(!!!)
2:保护模式
操作系统接管CPU后.
会使CPU进入保护模式.
这时候可以发挥80x86的所有威力..
包括权限分级.内存分页.等等等等各种功能

  1.虚拟8086模式是运行在保护模式中的实模式,为了在32位保护模式下执行纯16位程序。它不是一个真正的CPU模式,还属于保护模式。  
   
  2.保护模式同实模式的根本区别是进程内存受保护与否。可寻址空间的区别只是这一原因的果。  
  实模式将整个物理内存看成分段的区域,程序代码和数据位于不同区域,系统程序和用户程序没有区别对待,而且每一个指针都是指向"实在"的物理地址。这样一来,用户程序的一个指针如果指向了系统程序区域或其他用户程序区域,并改变了值,那么对于这个被修改的系统程序或用户程序,其后果就很可能是灾难性的。为了克服这种低劣的内存管理方式,处理器厂商开发出保护模式。这样,物理内存地址不能直接被程序访问,程序内部的地址(虚拟地址)要由操作系统转化为物理地址去访问,程序对此一无所知。至此,进程(这时我们可以称程序为进程了)有了严格的边界,任何其他进程根本没有办法访问不属于自己的物理内存区域,甚至在自己的虚拟地址范围内也不是可以任意访问的,因为有一些虚拟区域已经被放进一些公共系统运行库。这些区域也不能随便修改,若修改就会有:   SIGSEGV(linux   段错误);非法内存访问对话框(windows   对话框)。  
   
  CPU启动环境为16位实模式,之后可以切换到保护模式。但从保护模式无法切换回实模式  
   
  3.事实上,现在的64位奔腾4处理器,拥有三种基本模式和一种扩展模式,  
          a)基本模式:  
              ****保护模式:纯32位保护执行环境。  
              ****实模式:纯16位无保护执行环境。  
              ****系统管理模式:当SMI引脚为有效进入系统管理模式,首先保存当前的CPU上下文。它有独立的地址空间,用来执行电源管理或系统安全方面的指令。  
          b)扩展模式:****IA-32e模式,64位操作系统运行在该模式。该模式有两种子模式:  
                    1)**兼容模式:该模式下,64位操作系统运行在32位兼容环境,能正常运行16,32位应用程序就像基本的保护模式一样,访问32位地址空间,但不能运行纯16位实模式程序(就是不能运行虚拟86模式程序了)。  
                    2)**64位模式:在该模式下,处理器完全执行64位指令,使用64位地址空间和64操作数,运行16,32位程序必须切换到兼容模式。  
          IA-32e子模式的切换完全基于代码段寄存器。这样一来,运行在IA-32e模式中(64位)的OS完全可以无缝的运行所有16,32,64为应用程序,通过设置32位后的CS。

从80386开始,cpu有三种工作方式:实模式,保护模式和虚拟8086模式。只有在刚刚启动的时候是real-mode,等到linux操作系统运行起来以后就运行在保护模式。  
  实模式只能访问地址在1M以下的内存称为常规内存,我们把地址在1M   以上的内存称为扩展内存。  
  在保护模式下,全部32条地址线有效,可寻址高达4G字节的物理地址空间;  
  扩充的存储器分段管理机制和可选的存储器分页管理机制,不仅为存储器共享和保护提供了硬件支持,而且为实现虚拟存储器提供了硬件支持;  
  支持多任务,能够快速地进行任务切换和保护任务环境;  
  4个特权级和完善的特权检查机制,既能实现资源共享又能保证代码和数据的安全和保密及任务的隔离;  
  支持虚拟8086方式,便于执行8086程序。

————————————————————————————————————————————————————
我认为只所以有实模式和保护模式完全是由历史的原因所造成的.
1. 什么叫实模式?
所谓的实模式就是CPU的最大寻址空间为1M的一种模式,也就是8086 CPU的模式。
2. 什么叫保护模式?
所谓的保护模式就是CPU寻址空间在1M以上的模式。保护模式又分为16位的保护模式和32位的保护模式。

由于8086 CPU外部有20根地址线,故它所能够寻址的最大地址空间为1M,但8086的内部寄存器的长度为16位,用传统的寄存器寻址方式所能够访问的最大地址空间为64K,为了
能够对64K~1M的地址空间进行寻址,Intel采用了另外一种寻址方式即----段:偏移量寻址方式,其中段和偏移量都用16位的寄存器表示,这种寻址方式成功的解决了对64K~1M地址空间的寻址。但这时新的问题出现了,这种寻址方式下的最高地址为0xFFFF:0xFFFF,相应的最大寻址空间就成了0xFFFF*16+0xFFFF+1=0x10FFF0,但8086CPU只有20根地址线,那么当程序给出1M以上的地址时怎么办呢? Intel就采用了另外一种叫做wrap-around的技术,即当程序给出1M以上的地址时,地址重新从0开始计算,也就是把地址对1M求模。
我们知道80286 CPU的外部有24根地址线,能够对1M以上的地址空间进行寻址,为了保持80286CPU对8086 CPU的兼容性,Intel为80286设计了两种模式即8086模式(实模式)和
80286模式(16位的保护模式)。在8086模式下(实模式), 80286除了主频比8086快之外,别的操作和8086一样,即当CPU遇到1M以上的地址时就对该地址重新计算。在80286模式(16位的保护模式)下,CPU能够正常访问1M以上的地址空间,这时所能访问的最大地址空间为0x10FFF0。虽然80286有24根地址线,理论上的最大寻址空间为16M,但由于80286的内部寄存器为16位,这就限制了 80286最大只能寻址到0xFFFF:0xFFFF,但这时所能够寻址的最大空间毕竟增加了63.984375k(0xFFF0)。Intel是通过设置A20 gate实现了CPU实模式和保护模式之间的切换的。

抱歉!评论已关闭.