Chinaunix首页 | 论坛 | 博客
  • 博客访问: 660260
  • 博文数量: 171
  • 博客积分: 2246
  • 博客等级: 大尉
  • 技术积分: 1574
  • 用 户 组: 普通用户
  • 注册时间: 2012-05-31 11:45
文章分类

全部博文(171)

文章存档

2018年(3)

2017年(4)

2015年(1)

2014年(20)

2013年(57)

2012年(86)

分类: LINUX

2012-12-26 17:47:49

原文: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指令的格式为

 

   0eah  offset              segment

   byte1 byte2 byte3 byte4   byte5 byte6


点击(此处)折叠或打开

  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

阅读(1016) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~