• 第十四课 局部段描述符的使用


      前面我们使用的都是全局段描述符表,现在我们来分析局部段描述符表的使用。

     什么是LDT(Local Descriptor Table)?

      局部段描述符表:

        本质是一个段描述符表,用于定义段描述符

        与GDT类似,可以看做“段描述符的数组”

        通过定义选择子访问局部段描述符表中的元素

    局部段描述符的选择子和全局描述符的选择子在结构上是完全一样的,3-15位为描述符索引值,LDT选择子的第二位恒为1,1-0位为RPL。

    局部段描述符表就是一段内存,里面的每一项是一个局部段描述符(第0项也是有意义的),用于描述一段内存。

    CPU中有一个专用寄存器专门指向局部段描述符表。(先定义一个常量   DA_LDT    equ  0x82),在全局段描述符表中定义局部段描述符表的描述项时,需要用到属性,这个属性就是DA_LDT。

     局部段描述符表的注意事项:

      局部段描述符表需要在全局段描述符表中注册(增加描述项)

      通过对应的选择子加载局部段描述符(lldt)

      局部段描述符表从第0项开始使用(different  from  GDT)

    LDT的意义:

      代码层面的意义:

        分级管理功能相同意义不同的段(如:多个代码段),全局段描述符表也是有界限的,如果分段过多,则全局段描述符表有可能不够用。而局部段描述符表不限制描述符的个数。引入这种分级管理描述符的机制,可以定义无数个段。

      系统层面的意义:

        实现多任务的基础要素(每个任务对应一系列不同的段)

     LDT的定义与使用:

      1、定义独立功能相关的段(代码段、数据段、栈段)

      2、将目标段描述符组成局部段描述符表(LDT)

      3、为各个段描述符定义选择子(SA_TIL)

      4、在GDT中定义LDT的段描述符,并定义选择子

     下面给出示例程序,演示局部段描述符的使用。

    inc.asm更新如下:

     1 ; Segment Attribute
     2 DA_32    equ    0x4000
     3 DA_DR    equ    0x90
     4 DA_DRW   equ    0x92
     5 DA_DRWA  equ    0x93
     6 DA_C     equ    0x98
     7 DA_CR    equ    0x9A
     8 DA_CCO   equ    0x9C
     9 DA_CCOR  equ    0x9E
    10 
    11 ; Special Attribute
    12 DA_LDT     equ    0x82
    13 
    14 ; Selector Attribute
    15 SA_RPL0    equ    0
    16 SA_RPL1    equ    1
    17 SA_RPL2    equ    2
    18 SA_RPL3    equ    3
    19 
    20 SA_TIG    equ    0
    21 SA_TIL    equ    4
    22 
    23 ; 描述符
    24 ; usage: Descriptor Base, Limit, Attr
    25 ;        Base:  dd
    26 ;        Limit: dd (low 20 bits available)
    27 ;        Attr:  dw (lower 4 bits of higher byte are always 0)
    28 %macro Descriptor 3                              ; 段基址, 段界限, 段属性
    29     dw    %2 & 0xFFFF                         ; 段界限1
    30     dw    %1 & 0xFFFF                         ; 段基址1
    31     db    (%1 >> 16) & 0xFF                   ; 段基址2
    32     dw    ((%2 >> 8) & 0xF00) | (%3 & 0xF0FF) ; 属性1 + 段界限2 + 属性2
    33     db    (%1 >> 24) & 0xFF                   ; 段基址3
    34 %endmacro                                     ; 共 8 字节

    我们增加了第12行的宏定义。

    loader.asm的程序如下:

      1 %include "inc.asm"
      2 
      3 org 0x9000
      4 
      5 jmp ENTRY_SEGMENT
      6 
      7 [section .gdt]
      8 ; GDT definition
      9 ;                                 段基址,       段界限,       段属性
     10 GDT_ENTRY       :     Descriptor    0,            0,           0
     11 CODE32_DESC     :     Descriptor    0,    Code32SegLen  - 1,   DA_C + DA_32
     12 VIDEO_DESC      :     Descriptor 0xB8000,       0x07FFF,       DA_DRWA + DA_32
     13 DATA32_DESC     :     Descriptor    0,    Data32SegLen  - 1,   DA_DR + DA_32
     14 STACK32_DESC    :     Descriptor    0,      TopOfStack32,      DA_DRW + DA_32    
     15 CODE16_DESC     :     Descriptor    0,           0xFFFF,       DA_C
     16 UPDATE_DESC     :     Descriptor    0,           0xFFFF,       DA_DRW
     17 TASK_A_LDT_DESC   :     Descriptor    0,       TaskALdtLen - 1,  DA_LDT
     18 ; GDT end
     19 
     20 GdtLen    equ   $ - GDT_ENTRY
     21 
     22 GdtPtr:
     23           dw   GdtLen - 1
     24           dd   0
     25           
     26           
     27 ; GDT Selector
     28 
     29 Code32Selector    equ (0x0001 << 3) + SA_TIG + SA_RPL0
     30 VideoSelector     equ (0x0002 << 3) + SA_TIG + SA_RPL0
     31 Data32Selector    equ (0x0003 << 3) + SA_TIG + SA_RPL0
     32 Stack32Selector   equ (0x0004 << 3) + SA_TIG + SA_RPL0
     33 Code16Selector    equ (0x0005 << 3) + SA_TIG + SA_RPL0
     34 UpdateSelector    equ (0x0006 << 3) + SA_TIG + SA_RPL0
     35 TaskALdtSelector  equ (0x0007 << 3) + SA_TIG + SA_RPL0
     36 ; end of [section .gdt]
     37 
     38 TopOfStack16    equ  0x7c00
     39 
     40 [section .dat]
     41 [bits 32]
     42 DATA32_SEGMENT:
     43     DTOS                 db    "D.T.OS!", 0
     44     DTOS_OFFSET          equ   DTOS - $$
     45     HELLO_WORLD          db    "Hello World!", 0
     46     HELLO_WORLD_OFFSET   equ  HELLO_WORLD - $$
     47 
     48 Data32SegLen  equ $ - DATA32_SEGMENT
     49 
     50 [section .s16]
     51 [bits 16]
     52 ENTRY_SEGMENT:
     53     mov ax, cs
     54     mov ds, ax
     55     mov es, ax
     56     mov ss, ax
     57     mov sp, TopOfStack16
     58     
     59     mov [BACK_TO_REAL_MODE + 3], ax 
     60     
     61     ; initialize GDT for 32 bits code segment
     62     mov esi, CODE32_SEGMENT
     63     mov edi, CODE32_DESC
     64     
     65     call InitDescItem
     66     
     67     mov esi, DATA32_SEGMENT
     68     mov edi, DATA32_DESC
     69     
     70     call InitDescItem
     71     
     72     mov esi, DATA32_SEGMENT
     73     mov edi, STACK32_DESC
     74     
     75     call InitDescItem
     76     
     77     mov esi, CODE16_SEGMENT
     78     mov edi, CODE16_DESC
     79     
     80     call InitDescItem
     81     
     82     mov esi, TASK_A_LDT_ENTRY
     83     mov edi, TASK_A_LDT_DESC
     84     
     85     call InitDescItem
     86     
     87     mov esi, TASK_A_CODE32_SEGMENT
     88     mov edi, TASK_A_CODE32_DESC
     89     
     90     call InitDescItem
     91     
     92     mov esi, TASK_A_DATA32_SEGMENT
     93     mov edi, TASK_A_DATA32_DESC
     94     
     95     call InitDescItem
     96     
     97     mov esi, TASK_A_STACK32_SEGMENT
     98     mov edi, TASK_A_STACK32_DESC
     99     
    100     call InitDescItem
    101     
    102     ; initialize GDT pointer struct
    103     mov eax, 0
    104     mov ax, ds
    105     shl eax, 4
    106     add eax, GDT_ENTRY
    107     mov dword [GdtPtr + 2], eax
    108 
    109     ; 1. load GDT
    110     lgdt [GdtPtr]
    111     
    112     ; 2. close interrupt
    113     cli 
    114     
    115     ; 3. open A20
    116     in al, 0x92
    117     or al, 00000010b
    118     out 0x92, al
    119     
    120     ; 4. enter protect mode
    121     mov eax, cr0
    122     or eax, 0x01
    123     mov cr0, eax
    124     
    125     ; 5. jump to 32 bits code
    126     jmp dword Code32Selector : 0
    127 
    128 BACK_ENTRY_SEGMENT:
    129         mov ax, cs
    130         mov ds, ax
    131         mov es, ax
    132         mov ss, ax
    133         mov sp, TopOfStack16
    134         
    135         in al, 0x92
    136         and al, 11111101b
    137         out 0x92, al
    138         
    139         sti 
    140         
    141         mov bp, HELLO_WORLD
    142         mov cx, 12
    143         mov dx, 0
    144         mov ax, 0x1301
    145         mov bx, 0x0007
    146         int 0x10
    147         
    148         jmp $
    149 
    150 ; esi    --> code segment label
    151 ; edi    --> descriptor label
    152 InitDescItem:
    153     push eax
    154     
    155     mov eax, 0
    156     mov ax, cs
    157     shl eax, 4
    158     add eax, esi
    159     mov word [edi + 2], ax
    160     shr eax, 16
    161     mov byte [edi + 4], al
    162     mov byte [edi + 7], ah
    163     
    164     pop eax
    165     
    166     ret
    167     
    168 
    169 [section .16]
    170 [bits 16]
    171 CODE16_SEGMENT:
    172     mov ax, UpdateSelector
    173     mov ds, ax
    174     mov es, ax
    175     mov fs, ax
    176     mov gs, ax
    177     mov ss, ax
    178     
    179     mov eax, cr0
    180     and al, 11111110b
    181     mov cr0, eax
    182     
    183 BACK_TO_REAL_MODE:
    184     jmp 0 : BACK_ENTRY_SEGMENT
    185     
    186 Code16SegLen    equ $ - CODE16_SEGMENT
    187 
    188     
    189 [section .s32]
    190 [bits 32]
    191 CODE32_SEGMENT:
    192     mov ax, VideoSelector
    193     mov gs, ax
    194     
    195     mov ax, Stack32Selector
    196     mov ss, ax
    197     
    198     mov eax, TopOfStack32
    199     mov esp, eax
    200     
    201     mov ax, Data32Selector
    202     mov ds, ax
    203     
    204     mov ebp, DTOS_OFFSET
    205     mov bx, 0x0C
    206     mov dh, 12
    207     mov dl, 33
    208     
    209     call PrintString
    210     
    211     mov ebp, HELLO_WORLD_OFFSET
    212     mov bx, 0x0C
    213     mov dh, 13
    214     mov dl, 30
    215     
    216     call PrintString
    217     
    218     mov ax, TaskALdtSelector
    219     lldt ax
    220     
    221     jmp TaskACode32Selector : 0
    222     
    223     ;jmp Code16Selector : 0
    224 
    225 ; ds:ebp   --> string address
    226 ; bx       --> attribute
    227 ; dx       --> dh : row, dl : col
    228 PrintString:
    229     push ebp
    230     push eax
    231     push edi 
    232     push cx
    233     push dx
    234     
    235 print:
    236     mov cl, [ds:ebp]
    237     cmp cl, 0
    238     je end
    239     mov eax, 80
    240     mul dh
    241     add al, dl
    242     shl eax, 1
    243     mov edi, eax
    244     mov ah, bl
    245     mov al, cl
    246     mov [gs:edi], ax
    247     inc ebp
    248     inc dl
    249     jmp print
    250     
    251 end:
    252     pop dx
    253     pop cx
    254     pop edi
    255     pop eax
    256     pop ebp
    257     
    258     ret
    259 
    260 Code32SegLen    equ    $ - CODE32_SEGMENT
    261 
    262 [section .gs]
    263 [bits 32]
    264 STACK32_SEGMENT:
    265     times 1014 * 4 db 0
    266     
    267 Stack32SegLen    equ $ - STACK32_SEGMENT
    268 TopOfStack32    equ Stack32SegLen - 1
    269 
    270 
    271 ; ==================================
    272 ;        
    273 ;        Task A Code Segment
    274 ;
    275 ;===================================
    276 [section .task-a-ldt]
    277 ; Task A LDT definition
    278 ;                                        段基址                     段界限                段属性
    279 
    280 TASK_A_LDT_ENTRY:
    281 TASK_A_CODE32_DESC    :   Descriptor       0,               TaskACode32SegLen - 1,  DA_C + DA_32
    282 TASK_A_DATA32_DESC    :   Descriptor       0,               TaskAData32SegLen - 1,  DA_DR + DA_32
    283 TASK_A_STACK32_DESC   :   Descriptor       0,               TaskAStack32SegLen - 1, DA_DRW + DA_32
    284 
    285 TaskALdtLen        equ   $ - TASK_A_LDT_ENTRY
    286 
    287 ; Task A LDT  Selector
    288 TaskACode32Selector        equ  (0x0000 << 3) + SA_TIL + SA_RPL0
    289 TaskAData32Selector     equ     (0x0001 << 3) + SA_TIL + SA_RPL0
    290 TaskAStack32Selector    equ  (0x0002 << 3) + SA_TIL + SA_RPL0
    291 
    292 [section .task-a-dat]
    293 [bits 32]
    294 TASK_A_DATA32_SEGMENT:
    295     TASK_A_STRING        db   "This is Task A", 0
    296     TASK_STRING_OFFSET    equ     TASK_A_STRING - $$
    297     
    298 TaskAData32SegLen    equ $ - TASK_A_DATA32_SEGMENT
    299 
    300 [section .task-a-gs]
    301 [bits 32]
    302 TASK_A_STACK32_SEGMENT:
    303     times 1024 db 0
    304     
    305 TaskAStack32SegLen    equ     $ - TASK_A_STACK32_SEGMENT
    306 TaskATopOfStack32    equ     TaskAStack32SegLen - 1
    307 
    308 [section .task-a-s32]
    309 [bits 32]
    310 TASK_A_CODE32_SEGMENT:
    311 
    312     mov ax, VideoSelector
    313     mov gs, ax
    314     
    315     mov ax, TaskAStack32Selector
    316     mov ss, ax
    317     
    318     mov eax, TaskATopOfStack32
    319     mov esp, eax
    320     
    321     mov ax, TaskAData32Selector
    322     mov ds, ax
    323     
    324     jmp $
    325     
    326 TaskACode32SegLen     equ  $ - TASK_A_CODE32_SEGMENT

    从271行开始,我们定义了代表LDT段描述符表本身的段,定义了LDT下的代码段、数据段、栈段。在代码段中,我们加载了相应的段寄存器,最终程序停在原地。

    在第17行为LDT段描述符表本身占用的内存增加了段描述符项,用来描述这段内存。

    第35行增加了LDT段描述符表所在段的选择子。

    218-221行,我们添加了三行程序,作用为加载LDT段描述符表,跳转到LDT段描述符表描述的代码段去执行。

    执行结果如下:

     

    我们在LDT描述的代码段中加入以下打印程序:

    在324-329行加入了打印字符串的功能,这个PrintString函数是在全局段描述符表的代码段中定义的。

    执行结果如下:

    我们看到发生了CPU硬件复位。

    因为PrintString函数不是属于LDT中的代码段的,我们直接调用它导致了越界,从而CPU复位。因为现在的选择子是LDT段描述符中的选择子,即使PrintString代表的偏移地址是相同的也会发生错误。

    我们将打印相关的函数复制一份到LDT描述符下的代码段中,如下:

      1 %include "inc.asm"
      2 
      3 org 0x9000
      4 
      5 jmp ENTRY_SEGMENT
      6 
      7 [section .gdt]
      8 ; GDT definition
      9 ;                                 段基址,       段界限,       段属性
     10 GDT_ENTRY       :     Descriptor    0,            0,           0
     11 CODE32_DESC     :     Descriptor    0,    Code32SegLen  - 1,   DA_C + DA_32
     12 VIDEO_DESC      :     Descriptor 0xB8000,       0x07FFF,       DA_DRWA + DA_32
     13 DATA32_DESC     :     Descriptor    0,    Data32SegLen  - 1,   DA_DR + DA_32
     14 STACK32_DESC    :     Descriptor    0,      TopOfStack32,      DA_DRW + DA_32    
     15 CODE16_DESC     :     Descriptor    0,           0xFFFF,       DA_C
     16 UPDATE_DESC     :     Descriptor    0,           0xFFFF,       DA_DRW
     17 TASK_A_LDT_DESC   :     Descriptor    0,       TaskALdtLen - 1,  DA_LDT
     18 ; GDT end
     19 
     20 GdtLen    equ   $ - GDT_ENTRY
     21 
     22 GdtPtr:
     23           dw   GdtLen - 1
     24           dd   0
     25           
     26           
     27 ; GDT Selector
     28 
     29 Code32Selector    equ (0x0001 << 3) + SA_TIG + SA_RPL0
     30 VideoSelector     equ (0x0002 << 3) + SA_TIG + SA_RPL0
     31 Data32Selector    equ (0x0003 << 3) + SA_TIG + SA_RPL0
     32 Stack32Selector   equ (0x0004 << 3) + SA_TIG + SA_RPL0
     33 Code16Selector    equ (0x0005 << 3) + SA_TIG + SA_RPL0
     34 UpdateSelector    equ (0x0006 << 3) + SA_TIG + SA_RPL0
     35 TaskALdtSelector  equ (0x0007 << 3) + SA_TIG + SA_RPL0
     36 ; end of [section .gdt]
     37 
     38 TopOfStack16    equ  0x7c00
     39 
     40 [section .dat]
     41 [bits 32]
     42 DATA32_SEGMENT:
     43     DTOS                 db    "D.T.OS!", 0
     44     DTOS_OFFSET          equ   DTOS - $$
     45     HELLO_WORLD          db    "Hello World!", 0
     46     HELLO_WORLD_OFFSET   equ  HELLO_WORLD - $$
     47 
     48 Data32SegLen  equ $ - DATA32_SEGMENT
     49 
     50 [section .s16]
     51 [bits 16]
     52 ENTRY_SEGMENT:
     53     mov ax, cs
     54     mov ds, ax
     55     mov es, ax
     56     mov ss, ax
     57     mov sp, TopOfStack16
     58     
     59     mov [BACK_TO_REAL_MODE + 3], ax 
     60     
     61     ; initialize GDT for 32 bits code segment
     62     mov esi, CODE32_SEGMENT
     63     mov edi, CODE32_DESC
     64     
     65     call InitDescItem
     66     
     67     mov esi, DATA32_SEGMENT
     68     mov edi, DATA32_DESC
     69     
     70     call InitDescItem
     71     
     72     mov esi, DATA32_SEGMENT
     73     mov edi, STACK32_DESC
     74     
     75     call InitDescItem
     76     
     77     mov esi, CODE16_SEGMENT
     78     mov edi, CODE16_DESC
     79     
     80     call InitDescItem
     81     
     82     mov esi, TASK_A_LDT_ENTRY
     83     mov edi, TASK_A_LDT_DESC
     84     
     85     call InitDescItem
     86     
     87     mov esi, TASK_A_CODE32_SEGMENT
     88     mov edi, TASK_A_CODE32_DESC
     89     
     90     call InitDescItem
     91     
     92     mov esi, TASK_A_DATA32_SEGMENT
     93     mov edi, TASK_A_DATA32_DESC
     94     
     95     call InitDescItem
     96     
     97     mov esi, TASK_A_STACK32_SEGMENT
     98     mov edi, TASK_A_STACK32_DESC
     99     
    100     call InitDescItem
    101     
    102     ; initialize GDT pointer struct
    103     mov eax, 0
    104     mov ax, ds
    105     shl eax, 4
    106     add eax, GDT_ENTRY
    107     mov dword [GdtPtr + 2], eax
    108 
    109     ; 1. load GDT
    110     lgdt [GdtPtr]
    111     
    112     ; 2. close interrupt
    113     cli 
    114     
    115     ; 3. open A20
    116     in al, 0x92
    117     or al, 00000010b
    118     out 0x92, al
    119     
    120     ; 4. enter protect mode
    121     mov eax, cr0
    122     or eax, 0x01
    123     mov cr0, eax
    124     
    125     ; 5. jump to 32 bits code
    126     jmp dword Code32Selector : 0
    127 
    128 BACK_ENTRY_SEGMENT:
    129         mov ax, cs
    130         mov ds, ax
    131         mov es, ax
    132         mov ss, ax
    133         mov sp, TopOfStack16
    134         
    135         in al, 0x92
    136         and al, 11111101b
    137         out 0x92, al
    138         
    139         sti 
    140         
    141         mov bp, HELLO_WORLD
    142         mov cx, 12
    143         mov dx, 0
    144         mov ax, 0x1301
    145         mov bx, 0x0007
    146         int 0x10
    147         
    148         jmp $
    149 
    150 ; esi    --> code segment label
    151 ; edi    --> descriptor label
    152 InitDescItem:
    153     push eax
    154     
    155     mov eax, 0
    156     mov ax, cs
    157     shl eax, 4
    158     add eax, esi
    159     mov word [edi + 2], ax
    160     shr eax, 16
    161     mov byte [edi + 4], al
    162     mov byte [edi + 7], ah
    163     
    164     pop eax
    165     
    166     ret
    167     
    168 
    169 [section .16]
    170 [bits 16]
    171 CODE16_SEGMENT:
    172     mov ax, UpdateSelector
    173     mov ds, ax
    174     mov es, ax
    175     mov fs, ax
    176     mov gs, ax
    177     mov ss, ax
    178     
    179     mov eax, cr0
    180     and al, 11111110b
    181     mov cr0, eax
    182     
    183 BACK_TO_REAL_MODE:
    184     jmp 0 : BACK_ENTRY_SEGMENT
    185     
    186 Code16SegLen    equ $ - CODE16_SEGMENT
    187 
    188     
    189 [section .s32]
    190 [bits 32]
    191 CODE32_SEGMENT:
    192     mov ax, VideoSelector
    193     mov gs, ax
    194     
    195     mov ax, Stack32Selector
    196     mov ss, ax
    197     
    198     mov eax, TopOfStack32
    199     mov esp, eax
    200     
    201     mov ax, Data32Selector
    202     mov ds, ax
    203     
    204     mov ebp, DTOS_OFFSET
    205     mov bx, 0x0C
    206     mov dh, 12
    207     mov dl, 33
    208     
    209     call PrintString
    210     
    211     mov ebp, HELLO_WORLD_OFFSET
    212     mov bx, 0x0C
    213     mov dh, 13
    214     mov dl, 30
    215     
    216     call PrintString
    217     
    218     mov ax, TaskALdtSelector
    219     lldt ax
    220     
    221     jmp TaskACode32Selector : 0
    222     
    223     ;jmp Code16Selector : 0
    224 
    225     
    226 ; ds:ebp   --> string address
    227 ; bx       --> attribute
    228 ; dx       --> dh : row, dl : col
    229 PrintString:
    230     push ebp
    231     push eax
    232     push edi 
    233     push cx
    234     push dx
    235     
    236 print:
    237     mov cl, [ds:ebp]
    238     cmp cl, 0
    239     je end
    240     mov eax, 80
    241     mul dh
    242     add al, dl
    243     shl eax, 1
    244     mov edi, eax
    245     mov ah, bl
    246     mov al, cl
    247     mov [gs:edi], ax
    248     inc ebp
    249     inc dl
    250     jmp print
    251     
    252 end:
    253     pop dx
    254     pop cx
    255     pop edi
    256     pop eax
    257     pop ebp
    258     
    259     ret
    260 
    261 Code32SegLen    equ    $ - CODE32_SEGMENT
    262 
    263 [section .gs]
    264 [bits 32]
    265 STACK32_SEGMENT:
    266     times 1014 * 4 db 0
    267     
    268 Stack32SegLen    equ $ - STACK32_SEGMENT
    269 TopOfStack32    equ Stack32SegLen - 1
    270 
    271 
    272 ; ==================================
    273 ;        
    274 ;        Task A Code Segment
    275 ;
    276 ;===================================
    277 [section .task-a-ldt]
    278 ; Task A LDT definition
    279 ;                                        段基址                     段界限                段属性
    280 
    281 TASK_A_LDT_ENTRY:
    282 TASK_A_CODE32_DESC    :   Descriptor       0,               TaskACode32SegLen - 1,  DA_C + DA_32
    283 TASK_A_DATA32_DESC    :   Descriptor       0,               TaskAData32SegLen - 1,  DA_DR + DA_32
    284 TASK_A_STACK32_DESC   :   Descriptor       0,               TaskAStack32SegLen - 1, DA_DRW + DA_32
    285 
    286 TaskALdtLen        equ   $ - TASK_A_LDT_ENTRY
    287 
    288 ; Task A LDT  Selector
    289 TaskACode32Selector        equ  (0x0000 << 3) + SA_TIL + SA_RPL0
    290 TaskAData32Selector     equ     (0x0001 << 3) + SA_TIL + SA_RPL0
    291 TaskAStack32Selector    equ  (0x0002 << 3) + SA_TIL + SA_RPL0
    292 
    293 [section .task-a-dat]
    294 [bits 32]
    295 TASK_A_DATA32_SEGMENT:
    296     TASK_A_STRING        db   "This is Task A", 0
    297     TASK_A_STRING_OFFSET    equ     TASK_A_STRING - $$
    298     
    299 TaskAData32SegLen    equ $ - TASK_A_DATA32_SEGMENT
    300 
    301 [section .task-a-gs]
    302 [bits 32]
    303 TASK_A_STACK32_SEGMENT:
    304     times 1024 db 0
    305     
    306 TaskAStack32SegLen    equ     $ - TASK_A_STACK32_SEGMENT
    307 TaskATopOfStack32    equ     TaskAStack32SegLen - 1
    308 
    309 [section .task-a-s32]
    310 [bits 32]
    311 TASK_A_CODE32_SEGMENT:
    312 
    313     mov ax, VideoSelector
    314     mov gs, ax
    315     
    316     mov ax, TaskAStack32Selector
    317     mov ss, ax
    318     
    319     mov eax, TaskATopOfStack32
    320     mov esp, eax
    321     
    322     mov ax, TaskAData32Selector
    323     mov ds, ax
    324     
    325     mov ebp, TASK_A_STRING_OFFSET
    326     mov bx, 0x0c
    327     mov dh, 14
    328     mov dl, 29
    329     
    330     call TaskAPrintString
    331     
    332     jmp Code16Selector : 0
    333     
    334 ; ds:ebp   --> string address
    335 ; bx       --> attribute
    336 ; dx       --> dh : row, dl : col
    337 TaskAPrintString:
    338     push ebp
    339     push eax
    340     push edi 
    341     push cx
    342     push dx
    343     
    344 task_print:
    345     mov cl, [ds:ebp]
    346     cmp cl, 0
    347     je task_end
    348     mov eax, 80
    349     mul dh
    350     add al, dl
    351     shl eax, 1
    352     mov edi, eax
    353     mov ah, bl
    354     mov al, cl
    355     mov [gs:edi], ax
    356     inc ebp
    357     inc dl
    358     jmp task_print
    359     
    360 task_end:
    361     pop dx
    362     pop cx
    363     pop edi
    364     pop eax
    365     pop ebp
    366     
    367     ret
    368     
    369 TaskACode32SegLen     equ  $ - TASK_A_CODE32_SEGMENT

    我们复制了打印函数,在第332行跳转到16位的保护模式,进一步跳转到16位实模式。

    执行结果如下:

     

    小结:

    局部段描述符表用于组织功能相关的段

    局部段描述符表需要加载后才能正常使用

    局部段描述符表必须在全局段描述符表中注册

    通过局部段描述符表的选择子对其进行访问

    局部段描述符表时实现多任务的基础

  • 相关阅读:
    浅谈纯文本&&富文本&&Markdown区别
    浅谈CSS图片base64编码技术
    postman测试请求API:方式post、上传文件file
    Antd版本V3-->V4迁移问题:初始化调整
    浅谈switch语句的技巧
    react路由传参
    react dangerouslySetInnerHTML用法
    SPA单页应用的2种类型分页技术(React、Vue等组件化开发)
    (3)re模块(正则表达式模块)
    (2)hashlib模块(加密算法模块)
  • 原文地址:https://www.cnblogs.com/wanmeishenghuo/p/9477931.html
Copyright © 2020-2023  润新知