实模式到保护模式的那一跳

以前看的都是理论,今天拿起《自己动手写操作系统》,把其中的一个小例子改了一个验证自己的理解是否正确

原本是这样的

 1 ; ==========================================

 2 ; pmtest1.asm

 3 ; 编译方法:nasm pmtest1.asm -o pmtest1.com

 4 ; ==========================================

 5 

 6 %include    "pm.inc"    ; 常量, 宏, 以及一些说明

 7 

 8 org    0100h

 9     jmp    LABEL_BEGIN

10 

11 [SECTION .gdt]

12 ; GDT

13 ;                                         段基址,      段界限     , 属性

14 LABEL_GDT:        Descriptor           0,                0, 0             ; 空描述符

15 LABEL_DESC_CODE32:    Descriptor           0, SegCode32Len - 1, DA_C + DA_32    ; 非一致代码段, 32

16 LABEL_DESC_VIDEO:    Descriptor     0B8000h,           0ffffh, DA_DRW        ; 显存首地址

17 ; GDT 结束

18 

19 GdtLen        equ    $ - LABEL_GDT    ; GDT长度

20 GdtPtr        dw    GdtLen - 1    ; GDT界限

21         dd    0        ; GDT基地址

22 

23 ; GDT 选择子

24 SelectorCode32        equ    LABEL_DESC_CODE32    - LABEL_GDT

25 SelectorVideo        equ    LABEL_DESC_VIDEO    - LABEL_GDT

26 ; END of [SECTION .gdt]

27 

28 [SECTION .s16]

29 [BITS    16]

30 LABEL_BEGIN:

31     mov    ax, cs

32     mov    ds, ax

33     mov    es, ax

34     mov    ss, ax

35     mov    sp, 0100h

36 

37     ; 初始化 32 位代码段描述符

38     xor    eax, eax

39     mov    ax, cs

40     shl    eax, 4

41     add    eax, LABEL_SEG_CODE32

42     mov    word [LABEL_DESC_CODE32 + 2], ax

43     shr    eax, 16

44     mov    byte [LABEL_DESC_CODE32 + 4], al

45     mov    byte [LABEL_DESC_CODE32 + 7], ah

46 

47     ; 为加载 GDTR 作准备

48     xor    eax, eax

49     mov    ax, ds

50     shl    eax, 4

51     add    eax, LABEL_GDT        ; eax <- gdt 基地址

52     mov    dword [GdtPtr + 2], eax    ; [GdtPtr + 2] <- gdt 基地址

53 

54     ; 加载 GDTR

55     lgdt    [GdtPtr]

56 

57     ; 关中断

58     cli

59 

60     ; 打开地址线A20

61     in    al, 92h

62     or    al, 00000010b

63     out    92h, al

64 

65     ; 准备切换到保护模式

66     mov    eax, cr0

67     or    eax, 1

68     mov    cr0, eax

69 

70     ; 真正进入保护模式

71     jmp    dword SelectorCode32:0    ; 执行这一句会把 SelectorCode32 装入 cs, 并跳转到 Code32Selector:0  处,这一跳在这 72 ; END of [SECTION .s16]

73 

74 

75 [SECTION .s32]; 32 位代码段. 由实模式跳入.

76 [BITS    32]

77 

78 LABEL_SEG_CODE32:

79     mov    ax, SelectorVideo

80     mov    gs, ax            ; 视频段选择子(目的)

81 

82     mov    edi, (80 * 10 + 0) * 2    ; 屏幕第 10 行, 第 0 列。

83     mov    ah, 0Ch            ; 0000: 黑底    1100: 红字

84     mov    al, 'P'

85     mov    [gs:edi], ax

86 

87     ; 到此停止

88     jmp    $

89 

90 SegCode32Len    equ    $ - LABEL_SEG_CODE32

91 ; END of [SECTION .s32]

然后我第一次把代码改成了这样:

  1 ; 编译方法:nasm pmtest1.asm -o pmtest1.com

  2 ; ==========================================

  3 

  4 %include    "pm.inc"    ; 常量, 宏, 以及一些说明

  5 

  6 org    0100h

  7     jmp    LABEL_BEGIN

  8 

  9 [SECTION .gdt]

 10 ; GDT

 11 ;                                         段基址,      段界限     , 属性

 12 LABEL_GDT:        Descriptor           0,                0, 0             ; 空描述符

 13 LABEL_DESC_CODE32:    Descriptor           0, SegCode32Len - 1, DA_C + DA_32    ; 非一致代码段, 32

 14 LABEL_DESC_VIDEO:    Descriptor     0B8000h,           0ffffh, DA_DRW        ; 显存首地址

 15 ; GDT 结束

 16 

 17 GdtLen        equ    $ - LABEL_GDT    ; GDT长度

 18 GdtPtr        dw    GdtLen - 1    ; GDT界限

 19         dd    0        ; GDT基地址

 20 

 21 ; GDT 选择子

 22 SelectorCode32        equ    LABEL_DESC_CODE32    - LABEL_GDT

 23 SelectorVideo        equ    LABEL_DESC_VIDEO    - LABEL_GDT

 24 ; END of [SECTION .gdt]

 25 

 26 

 27 LABEL_SEG_CODE32:

 28     mov ax, SelectorVideo

 29     mov gs, ax          ; 视频段选择子(目的)

 30 

 31     mov edi, (80 * 10 + 0) * 2  ; 屏幕第 10 行, 第 0 列。

 32     mov ah, 0Ch         ; 0000: 黑底    1100: 红字

 33     mov al, 'P'

 34     mov [gs:edi], ax

 35 

 36     ; 到此停止

 37     jmp $

 38     SegCode32Len    equ $ - LABEL_SEG_CODE32

 39 

 40 

 41 

 42 

 43 

 44 

 45 [SECTION .s16]

 46 [BITS    16]

 47 LABEL_BEGIN:

 48     mov    ax, cs

 49     mov    ds, ax

 50     mov    es, ax

 51     mov    ss, ax

 52     mov    sp, 0100h

 53 

 54     ; 初始化 32 位代码段描述符

 55     xor    eax, eax

 56     mov    ax, cs

 57     shl    eax, 4

 58     add    eax, LABEL_SEG_CODE32

 59     mov    word [LABEL_DESC_CODE32 + 2], ax

 60     shr    eax, 16

 61     mov    byte [LABEL_DESC_CODE32 + 4], al

 62     mov    byte [LABEL_DESC_CODE32 + 7], ah

 63 

 64     ; 为加载 GDTR 作准备

 65     xor    eax, eax

 66     mov    ax, ds

 67     shl    eax, 4

 68     add    eax, LABEL_GDT        ; eax <- gdt 基地址

 69     mov    dword [GdtPtr + 2], eax    ; [GdtPtr + 2] <- gdt 基地址

 70 

 71     ; 加载 GDTR

 72     lgdt    [GdtPtr]

 73 

 74     ; 关中断

 75     cli

 76 

 77     ; 打开地址线A20

 78     in    al, 92h

 79     or    al, 00000010b

 80     out    92h, al

 81 

 82     ; 准备切换到保护模式

 83     mov    eax, cr0

 84     or    eax, 1

 85     mov    cr0, eax

 86 

 87     ; 真正进入保护模式

 88     jmp    dword SelectorCode32:0    ; 执行这一句会把 SelectorCode32 装入 cs, 并跳转到 Code32Selector:0 89 ; END of [SECTION .s16]

 90 

 91 

 92 [SECTION .s32]; 32 位代码段. 由实模式跳入.

 93 [BITS    32]

简单来说,就是把LABEL_SEG_CODE32这个段移到了前面,高兴的是编译通的过,遗憾的是运行不了,看了半天,没有想明白那是为什么,我以为我原来的理解有误呢,后来突然看到一个字眼:[SECTION .s32]

                       [BITS  32]

就是这两个东西出的错,这两个是对齐的作用,嗯,在把这两个小东西移到LABEL_SEG_CODE32的前面就可以了

最后是这样的:

 1 ;"t1.asm

 2 ; 编译方法:nasm pmtest1.asm -o pmtest1.com

 3 ; ==========================================

 4 

 5 %include    "pm.inc"    ; 常量, 宏, 以及一些说明

 6 

 7 org    0100h

 8     jmp    LABEL_BEGIN

 9 

10 [SECTION .gdt]

11 ; GDT

12 ;                                         段基址,      段界限     , 属性

13 LABEL_GDT:        Descriptor           0,                0, 0             ; 空描述符

14 LABEL_DESC_CODE32:    Descriptor           0, SegCode32Len - 1, DA_C + DA_32    ; 非一致代码段, 32

15 LABEL_DESC_VIDEO:    Descriptor     0B8000h,           0ffffh, DA_DRW        ; 显存首地址

16 ; GDT 结束

17 

18 GdtLen        equ    $ - LABEL_GDT    ; GDT长度

19 GdtPtr        dw    GdtLen - 1    ; GDT界限

20         dd    0        ; GDT基地址

21 

22 ; GDT 选择子

23 SelectorCode32        equ    LABEL_DESC_CODE32    - LABEL_GDT

24 SelectorVideo        equ    LABEL_DESC_VIDEO    - LABEL_GDT

25 ; END of [SECTION .gdt]

26 

27 [SECTION .s32]; 32 位代码段. 由实模式跳入.

28 [BITS   32]

29 LABEL_SEG_CODE32:

30     mov ax, SelectorVideo

31     mov gs, ax          ; 视频段选择子(目的)

32 

33     mov edi, (80 * 10 + 0) * 2  ; 屏幕第 10 行, 第 0 列。

34     mov ah, 0Ch         ; 0000: 黑底    1100: 红字

35     mov al, 'P'

36     mov [gs:edi], ax

37 

38     ;; 到此停止

39     jmp $

40     SegCode32Len    equ $ - LABEL_SEG_CODE32

41 

42 

43 

44 

45 

46 

47 [SECTION .s16]

48 [BITS    16]

49 LABEL_BEGIN:

50     mov    ax, cs

51     mov    ds, ax

52     mov    es, ax

53     mov    ss, ax

54     mov    sp, 0100h

55 

56     ; 初始化 32 位代码段描述符

57     xor    eax, eax

58     mov    ax, cs

59     shl    eax, 4

60     add    eax, LABEL_SEG_CODE32

61     mov    word [LABEL_DESC_CODE32 + 2], ax

62     shr    eax, 16

63     mov    byte [LABEL_DESC_CODE32 + 4], al

64     mov    byte [LABEL_DESC_CODE32 + 7], ah

65 

66     ; 为加载 GDTR 作准备

67     xor    eax, eax

68     mov    ax, ds

69     shl    eax, 4

70     add    eax, LABEL_GDT        ; eax <- gdt 基地址

71     mov    dword [GdtPtr + 2], eax    ; [GdtPtr + 2] <- gdt 基地址

72 

73     ; 加载 GDTR

74     lgdt    [GdtPtr]

75 

76     ; 关中断

77     cli

78 

79     ; 打开地址线A20

80     in    al, 92h

81     or    al, 00000010b

82     out    92h, al

83 

84     ; 准备切换到保护模式

85     mov    eax, cr0

86     or    eax, 1

87     mov    cr0, eax

88 

89     ; 真正进入保护模式

90     jmp    dword SelectorCode32:0    ; 执行这一句会把 SelectorCode32 装入 cs, 并跳转到 Code32Selector:091 ; END of [SECTION .s16]

92 

93 

94 [SECTION .s32]; 32 位代码段. 由实模式跳入.

95 [BITS    32]

嗯,对齐一定要注意

 

你可能感兴趣的:(模式)