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


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

    原本是这样的

     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]

    嗯,对齐一定要注意

     
  • 相关阅读:
    杂项
    hdu 2094
    hdu acm 1004
    android 重装sdk或者系统的时模拟器出现can open ****
    使用Java模拟操作系统高优先级算法
    各种语法解释及用法
    枚举与结构
    闭包
    socket
    异常
  • 原文地址:https://www.cnblogs.com/cdwodm/p/2886790.html
Copyright © 2020-2023  润新知