从保护模式到实模式的转换

本文详细介绍了从保护模式到实模式转换的关键步骤和注意事项,包括堆栈段的维护、段寄存器的规范设置、段界限的要求等,帮助开发者理解和解决相关问题。

来自:http://blog.csdn.net/sunacmer/article/details/5310280

弄了几天了,终于弄好了,呵呵,也得到了不少东西。从保护模式到是模式的转换一定要注意的有(转):

 

1、程序开始时在实模式下要有自己的堆栈段,进入保护模式前先暂存ss及sp的值至某内存处,以便从保护模式返回实模式后恢复到原先的堆栈。 

2、返回实模式前需把各段寄存器设置为规范段,包括SS也要设置 

3、返回实模式前必须在16位段返回,不能在32位段里返回实模式。 

4、返回实模式前的段必须定义在GDT中。 

5、在32位段下操作有关寄存器时,注意32位寄存器和16位寄存器的差别,类似于SP寄存器,应用使用ESP寄存器。 

6、在使用定义在LDT中的段时,一定要使用LLDT先加载LDT缓冲寄存器(LDTR)。 

7、用于返回实模式的代码段的段界限必须为0FFFFH,不能为实际长度,否则要么在跳转到实模式的时候出错要么在跳转到实模式后执行int 21H出错。(个人推测原因如下:80286开始为每个段寄存器增加了段描述符高速缓冲寄存器,而这些缓冲寄存器对于程序员是不可见的,且在实模式下是不能修改的,要想改变这些高速缓冲寄存器的值必须通过在保护模式下修改相应的段寄存器的选择子来实现,这也是为什么在返回实模式之前必须把DS、ES、FS、GS、SS设置为规范段的原因。但是CS是一个特殊的段,不能通过常规方式修改,只能通过段间跳转修改,而一旦跳到实模式后又不能修改了,所以就要求在返回实模式的段的段描述符必须符合实模式下的要求。实模式下的段长度是0FFFFH,也就是64K,如果用于返回实模式的段的段界限不是0FFFFH,会导致返回实模式后实模式下的CS段的高速缓冲寄存器的段长度还是保护模式时的段界限值,这是不正确的,所以要求用于返回实模式的段的段界限必须是0FFFFH。) 

ps:所谓规范段是指实模式下的标准段属性,一般段界限为0FFFFH,段属性为可读写。 

 

自己的认识是从保护模式到实模式转换的过程为从某个保护模式下的函数中跳到16位下,在16位模式下要做的工作是设置各个段寄存器和设置CR0,(此处需要特别特别注意的是段寄存器中的选择子必须是要定义在GDT中的,而且其段界限必须为0xffff,否则仍然可以跳回实模式,但是会有段界限异常),然后再跳到最开始引导的段中关A20和开中断(sti),之所以还要跳回最开始的引导段,是因为需要用jmp设置cs。

 

1.f和g段寄存器可以不设为Normal

2.Normal段界限必须为0xffff  不然仍可以返回,但会有段界限异常

3.code16所在的段界限可以不为0xffff

4.某个函数->16位关CR0&&设置段寄存器->跳到最开始引导的段关A20、开中断(之所以跳到开始引导的段是因为

需要用jmp语句设置cs为段0)

5.代码中将16位的代码放在了文件的最后,原来是放在DISPLAY前的,是因为碰到了如下奇怪的情况在生成bin文件后,jmp指令和下面的mov ax,VIDEOSELECTOR指令混淆了,CPU执行时仍然是按照32位的指令执行的,所以将jmp解释为32位的,而编译的文件中却是16位的,因此会误将mov的机器指令当做jmp指令中的操作数。

6.如5中所说,在源文件中将代码声明为16位([BITS 16])后,生成的机器码为16位的,而在CPU执行时却仍按32位指令执行,暂时还不知道是怎么回事,有时间再看看。

代码中需要注意的是在引导段中的这一句

mov [RETURN_JMP+3],ax

这一句的作用是将jmp指令中的段字节设为0。在16位模式下,段间jmp指令的格式为

            offset           segment

ea   byte1 byte2    byte3 byte4

在32位模式下段间jmp指令的格式为

 

                      offset                    segment

ea   byte1 byte2 byte3 byte4   byte5 byte6

[cpp]  view plain copy
  1. org 0x7c00  
  2.     jmp MAIN  
  3. ;数据结构  
  4. GDT:  
  5.     DEFAULT_SEG:  
  6.     dw 0,0,0,0  
  7.     CODE32_SEG:  
  8.     dw 0x07ff  
  9.     dw 0x0000  
  10.     dw 0x9a00  
  11.     dw 0x00cf  
  12.     DATA_SEG:  
  13.     dw 0x07ff  
  14.     dw 0x0000  
  15.     dw 0x9200  
  16.     dw 0x00cf  
  17.     TEST_DATA_SEG:  
  18.     dw 0x07ff  
  19.     dw 0x0000  
  20.     dw 0x9250;三字节的基址  
  21.     dw 0x00cf  
  22.     VIDEO_SEG:;0x20  
  23.     dw 0x07ff  
  24.     dw 0x8000  
  25.     dw 0x920B  
  26.     dw 0x00cf  
  27.     REAL_SEG:;0x28  
  28.     dw 0xffff  
  29.     dw 0x0000  
  30.     dw 0x9200  
  31.     dw 0x00cf  
  32.     CODE16_SEG:  
  33.     dw 0x07ff  
  34.     dw 0x0000  
  35.     dw 0x9a00  
  36.     dw 0x00cf  
  37.     CALL_GATE_SEG:  
  38.     dw 0x0000  
  39.     dw CODE_SELECTOR  
  40.     dw 0x8c00  
  41.     dw 0x0000  
  42. GDT_END:  
  43. GDTR:  
  44.     dw GDT_END-GDT-1  
  45.     dw GDT,0  
  46. DEFAULT_SELECTOR equ DEFAULT_SEG-GDT  
  47. CODE_SELECTOR equ CODE32_SEG-GDT  
  48. DATA_SELECTOR equ DATA_SEG-GDT  
  49. TEST_DATA_SELECTOR equ TEST_DATA_SEG-GDT  
  50. VIDEO_SELECTOR equ VIDEO_SEG-GDT  
  51. REAL_SEG_SELECTOR equ REAL_SEG-GDT  
  52. CODE16_SELECTOR equ CODE16_SEG-GDT  
  53. CALL_GATE equ CALL_GATE_SEG-GDT  
  54. [BITS 16]  
  55. MAIN:  
  56. mov ax,cs  
  57. mov ds,ax  
  58. mov gs,ax  
  59. mov [RETURN_JMP+3],ax  
  60. ;init code32  
  61. xor eax,eax  
  62. mov ax,cs  
  63. shl eax,4  
  64. add eax,DISPLAY  
  65. mov word [CODE32_SEG+2],ax  
  66. shr eax,16  
  67. mov byte [CODE32_SEG+4],al  
  68. mov byte [CODE32_SEG+7],ah  
  69. ;init code16  
  70. xor eax,eax  
  71. mov ax,cs  
  72. shl eax,4  
  73. add eax,BACK_TO_REAL  
  74. mov word [CODE16_SEG+2],ax  
  75. shr eax,16  
  76. mov byte [CODE16_SEG+4],al  
  77. mov byte [CODE16_SEG+7],ah  
  78. lgdt [GDTR]  
  79. cli  
  80. ;a20  
  81. in al,0x92  
  82. or al,00000010b  
  83. out 0x92,al  
  84. ;cr0  
  85. mov eax,cr0  
  86. or eax,00000001b  
  87. mov cr0,eax  
  88. call CALL_GATE:0  
  89. REAL_ENTRY:;00007cb8  
  90. mov ax,cs  
  91. mov ds,ax  
  92. mov es,ax  
  93. mov ss,ax  
  94. ;关A20  
  95. ;in al,0x92  
  96. ;and al,11111101b  
  97. ;out 0x92,al  
  98. ;开中断  
  99. sti  
  100. jmp $  
  101. [BITS 32]  
  102. DISPLAY:  
  103. mov ax,VIDEO_SELECTOR  
  104. mov gs,ax  
  105. mov ah,0x0c  
  106. mov al,'P'  
  107. mov edi,(80*0+0)*2  
  108. mov [gs:edi],ax  
  109. ;jmp $  
  110. jmp CODE16_SELECTOR:0  
  111. ;放在CODE16_SEG中  
  112. ;还在CODE16中,CS=0x0030  
  113. ;ALIGN 32  
  114. [BITS 16];指令是16位的,但CPU在32位模式下,取指时按32位取  
  115. BACK_TO_REAL:  
  116. mov ax,REAL_SEG_SELECTOR;mov eax,0xd88e0028  
  117. mov ds,ax  
  118. mov ds,ax  
  119. mov es,ax  
  120. ;mov fs,ax  
  121. mov gs,ax  
  122. mov ss,ax  
  123. mov eax,cr0  
  124. and al,11111110b;!!!!!!!!! 段界限异常  
  125. mov cr0,eax  
  126. RETURN_JMP:  
  127. jmp 0:REAL_ENTRY;jmp far b866:00007cb8  
  128. times 510-($-$) db 0  
  129. dw 0xaa55  
 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值