zoukankan      html  css  js  c++  java
  • 第十八课 特权级转移(上)

    这一节我们来研究从核心代码特权级转移到应用代码特权级。

    首先将boot.asm贴出来如下:

      1 org 0x7c00
      2 
      3 jmp short start
      4 nop
      5 
      6 define:
      7     BaseOfStack      equ 0x7c00
      8     BaseOfLoader     equ 0x9000
      9     RootEntryOffset  equ 19
     10     RootEntryLength  equ 14
     11     EntryItemLength  equ 32
     12     FatEntryOffset   equ 1
     13     FatEntryLength   equ 9
     14 
     15 header:
     16     BS_OEMName     db "D.T.Soft"
     17     BPB_BytsPerSec dw 512
     18     BPB_SecPerClus db 1
     19     BPB_RsvdSecCnt dw 1
     20     BPB_NumFATs    db 2
     21     BPB_RootEntCnt dw 224
     22     BPB_TotSec16   dw 2880
     23     BPB_Media      db 0xF0
     24     BPB_FATSz16    dw 9
     25     BPB_SecPerTrk  dw 18
     26     BPB_NumHeads   dw 2
     27     BPB_HiddSec    dd 0
     28     BPB_TotSec32   dd 0
     29     BS_DrvNum      db 0
     30     BS_Reserved1   db 0
     31     BS_BootSig     db 0x29
     32     BS_VolID       dd 0
     33     BS_VolLab      db "D.T.OS-0.01"
     34     BS_FileSysType db "FAT12   "
     35 
     36 start:
     37     mov ax, cs
     38     mov ss, ax
     39     mov ds, ax
     40     mov es, ax
     41     mov sp, BaseOfStack
     42     
     43     mov ax, RootEntryOffset
     44     mov cx, RootEntryLength
     45     mov bx, Buf
     46     
     47     call ReadSector
     48     
     49     mov si, Target
     50     mov cx, TarLen
     51     mov dx, 0
     52     
     53     call FindEntry
     54     
     55     cmp dx, 0
     56     jz output
     57     
     58     mov si, bx
     59     mov di, EntryItem
     60     mov cx, EntryItemLength
     61     
     62     call MemCpy
     63     
     64     mov ax, FatEntryLength
     65     mov cx, [BPB_BytsPerSec]
     66     mul cx
     67     mov bx, BaseOfLoader
     68     sub bx, ax
     69     
     70     mov ax, FatEntryOffset
     71     mov cx, FatEntryLength
     72     
     73     call ReadSector
     74     
     75     mov dx, [EntryItem + 0x1A]
     76     mov si, BaseOfLoader
     77     
     78 loading:
     79     mov ax, dx
     80     add ax, 31
     81     mov cx, 1
     82     push dx
     83     push bx
     84     mov bx, si
     85     call ReadSector
     86     pop bx
     87     pop cx
     88     call FatVec
     89     cmp dx, 0xFF7
     90     jnb BaseOfLoader     
     91     add si, 512
     92     jmp loading
     93     
     94 output:    
     95     mov bp, MsgStr
     96     mov cx, MsgLen
     97     call Print
     98     
     99 last:
    100     hlt
    101     jmp last    
    102 
    103 
    104 ; cx --> index
    105 ; bx --> fat table address
    106 ;
    107 ; return:
    108 ;     dx --> fat[index]
    109 FatVec:
    110     mov ax, cx
    111     mov cl, 2
    112     div cl
    113     
    114     push ax
    115     
    116     mov ah, 0
    117     mov cx, 3
    118     mul cx
    119     mov cx, ax
    120     
    121     pop ax
    122     
    123     cmp ah, 0
    124     jz even
    125     jmp odd
    126 
    127 even:    ; FatVec[j] = ( (Fat[i+1] & 0x0F) << 8 ) | Fat[i];
    128     mov dx, cx
    129     add dx, 1
    130     add dx, bx
    131     mov bp, dx
    132     mov dl, byte [bp]
    133     and dl, 0x0F
    134     shl dx, 8
    135     add cx, bx
    136     mov bp, cx
    137     or  dl, byte [bp]
    138     jmp return
    139     
    140 odd:     ; FatVec[j+1] = (Fat[i+2] << 4) | ( (Fat[i+1] >> 4) & 0x0F );
    141     mov dx, cx
    142     add dx, 2
    143     add dx, bx
    144     mov bp, dx
    145     mov dl, byte [bp]
    146     mov dh, 0
    147     shl dx, 4
    148     add cx, 1
    149     add cx, bx
    150     mov bp, cx
    151     mov cl, byte [bp]
    152     shr cl, 4
    153     and cl, 0x0F
    154     mov ch, 0
    155     or  dx, cx
    156 
    157 return: 
    158     ret
    159 
    160 ; ds:si --> source
    161 ; es:di --> destination
    162 ; cx    --> length
    163 MemCpy:
    164     
    165     cmp si, di
    166     
    167     ja btoe
    168     
    169     add si, cx
    170     add di, cx
    171     dec si
    172     dec di
    173     
    174     jmp etob
    175     
    176 btoe:
    177     cmp cx, 0
    178     jz done
    179     mov al, [si]
    180     mov byte [di], al
    181     inc si
    182     inc di
    183     dec cx
    184     jmp btoe
    185     
    186 etob: 
    187     cmp cx, 0
    188     jz done
    189     mov al, [si]
    190     mov byte [di], al
    191     dec si
    192     dec di
    193     dec cx
    194     jmp etob
    195 
    196 done:   
    197     ret
    198 
    199 ; es:bx --> root entry offset address
    200 ; ds:si --> target string
    201 ; cx    --> target length
    202 ;
    203 ; return:
    204 ;     (dx !=0 ) ? exist : noexist
    205 ;        exist --> bx is the target entry
    206 FindEntry:
    207     push cx
    208     
    209     mov dx, [BPB_RootEntCnt]
    210     mov bp, sp
    211     
    212 find:
    213     cmp dx, 0
    214     jz noexist
    215     mov di, bx
    216     mov cx, [bp]
    217     push si
    218     call MemCmp
    219     pop si
    220     cmp cx, 0
    221     jz exist
    222     add bx, 32
    223     dec dx
    224     jmp find
    225 
    226 exist:
    227 noexist: 
    228     pop cx
    229        
    230     ret
    231 
    232 ; ds:si --> source
    233 ; es:di --> destination
    234 ; cx    --> length
    235 ;
    236 ; return:
    237 ;        (cx == 0) ? equal : noequal
    238 MemCmp:
    239 
    240 compare:
    241     cmp cx, 0
    242     jz equal
    243     mov al, [si]
    244     cmp al, byte [di]
    245     jz goon
    246     jmp noequal
    247 goon:
    248     inc si
    249     inc di
    250     dec cx
    251     jmp compare
    252     
    253 equal: 
    254 noequal:   
    255 
    256     ret
    257 
    258 ; es:bp --> string address
    259 ; cx    --> string length
    260 Print:
    261     mov dx, 0
    262     mov ax, 0x1301
    263     mov bx, 0x0007
    264     int 0x10
    265     ret
    266 
    267 ; no parameter
    268 ResetFloppy:
    269     
    270     mov ah, 0x00
    271     mov dl, [BS_DrvNum]
    272     int 0x13
    273     
    274     ret
    275 
    276 ; ax    --> logic sector number
    277 ; cx    --> number of sector
    278 ; es:bx --> target address
    279 ReadSector:
    280     
    281     call ResetFloppy
    282     
    283     push bx
    284     push cx
    285     
    286     mov bl, [BPB_SecPerTrk]
    287     div bl
    288     mov cl, ah
    289     add cl, 1
    290     mov ch, al
    291     shr ch, 1
    292     mov dh, al
    293     and dh, 1
    294     mov dl, [BS_DrvNum]
    295     
    296     pop ax
    297     pop bx
    298     
    299     mov ah, 0x02
    300 
    301 read:    
    302     int 0x13
    303     jc read
    304     
    305     ret
    306 
    307 MsgStr db  "No LOADER ..."    
    308 MsgLen equ ($-MsgStr)
    309 Target db  "LOADER     "
    310 TarLen equ ($-Target)
    311 EntryItem times EntryItemLength db 0x00
    312 Buf:
    313     times 510-($-$$) db 0x00
    314     db 0x55, 0xaa

    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 ; Segment Privilege
    12 DA_DPL0  equ   0x00        ; DPL = 0
    13 DA_DPL1  equ   0x20        ; DPL = 1
    14 DA_DPL2  equ   0x40        ; DPL = 2
    15 DA_DPL3  equ   0x60        ; DPL = 3
    16 
    17 ; Special Attribute
    18 DA_LDT             equ        0x82
    19 DA_TaskGate        equ        0x85    ; 
    20 DA_386TSS        equ        0x89    ;
    21 DA_386CGate        equ        0x8C    ;
    22 DA_386IGate        equ        0x8E    ;
    23 DA_386tgATE        equ        0x8F    ;
    24 
    25 ; Selector Attribute
    26 SA_RPL0    equ    0
    27 SA_RPL1    equ    1
    28 SA_RPL2    equ    2
    29 SA_RPL3    equ    3
    30 
    31 SA_TIG    equ    0
    32 SA_TIL    equ    4
    33 
    34 ; 描述符
    35 ; usage: Descriptor Base, Limit, Attr
    36 ;        Base:  dd
    37 ;        Limit: dd (low 20 bits available)
    38 ;        Attr:  dw (lower 4 bits of higher byte are always 0)
    39 %macro Descriptor 3                              ; 段基址, 段界限, 段属性
    40     dw    %2 & 0xFFFF                         ; 段界限1
    41     dw    %1 & 0xFFFF                         ; 段基址1
    42     db    (%1 >> 16) & 0xFF                   ; 段基址2
    43     dw    ((%2 >> 8) & 0xF00) | (%3 & 0xF0FF) ; 属性1 + 段界限2 + 属性2
    44     db    (%1 >> 24) & 0xFF                   ; 段基址3
    45 %endmacro                                     ; 共 8 字节
    46 
    47 ;Gate
    48 ; usage : Gate Selector, Offset, DCount, Attr
    49 ;         Selector : dw
    50 ;          Offset   : dd
    51 ;          DCount   : db
    52 ;          Attr       : db
    53 %macro Gate 4
    54     dw        (%2 & 0xFFFF)                        ; pianyidizhi1
    55     dw        %1                                    ; xuanzezi
    56     dw        (%3 & 0x1F) | ((%4 << 8) & 0xFF00)    ; shu xing
    57     dw        ((%2 >> 16) & 0xFFFF)                ; pianyidizhi2
    58 %endmacro

    18-2节的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 + DA_DPL0
     12 VIDEO_DESC      :     Descriptor 0xB8000,       0x07FFF,       DA_DRWA + DA_32 + DA_DPL0
     13 DATA32_DESC     :     Descriptor    0,    Data32SegLen - 1,    DA_DR + DA_32 + DA_DPL0
     14 STACK32_DESC    :     Descriptor    0,      TopOfStack32,      DA_DRW + DA_32  + DA_DPL0
     15 FUNCTION_DESC   :     Descriptor    0,   FunctionSegLen - 1,   DA_C + DA_32 + DA_DPL0
     16 TASK_A_LDT_DESC :     Descriptor    0,      TaskALdtLen - 1,   DA_LDT + DA_DPL0
     17 ; GDT end
     18 
     19 GdtLen    equ   $ - GDT_ENTRY
     20 
     21 GdtPtr:
     22           dw   GdtLen - 1
     23           dd   0
     24           
     25           
     26 ; GDT Selector
     27 
     28 Code32Selector    equ (0x0001 << 3) + SA_TIG + SA_RPL0
     29 VideoSelector     equ (0x0002 << 3) + SA_TIG + SA_RPL0
     30 Data32Selector    equ (0x0003 << 3) + SA_TIG + SA_RPL0
     31 Stack32Selector   equ (0x0004 << 3) + SA_TIG + SA_RPL0
     32 FunctionSelector  equ (0x0005 << 3) + SA_TIG + SA_RPL0
     33 TaskALdtSelector  equ (0x0006 << 3) + SA_TIG + SA_RPL0
     34 ; end of [section .gdt]
     35 
     36 TopOfStack16    equ  0x7c00
     37 
     38 [section .s16]
     39 [bits 16]
     40 ENTRY_SEGMENT:
     41     mov ax, cs
     42     mov ds, ax
     43     mov es, ax
     44     mov ss, ax
     45     mov sp, TopOfStack16
     46     
     47     ; initialize GDT for 32 bits code segment
     48     mov esi, CODE32_SEGMENT
     49     mov edi, CODE32_DESC
     50     
     51     call InitDescItem
     52     
     53     mov esi, DATA32_SEGMENT
     54     mov edi, DATA32_DESC
     55     
     56     call InitDescItem
     57     
     58     mov esi, STACK32_SEGMENT
     59     mov edi, STACK32_DESC
     60     
     61     call InitDescItem
     62     
     63     mov esi, FUNCTION_SEGMENT
     64     mov edi, FUNCTION_DESC
     65     
     66     call InitDescItem
     67     
     68     mov esi, TASK_A_LDT_ENTRY
     69     mov edi, TASK_A_LDT_DESC
     70     
     71     call InitDescItem
     72     
     73     mov esi, TASK_A_DATA32_SEGMENT
     74     mov edi, TASK_A_DATA32_DESC
     75     
     76     call InitDescItem
     77     
     78     mov esi, TASK_A_CODE32_SEGMENT
     79     mov edi, TASK_A_CODE32_DESC
     80     
     81     call InitDescItem
     82     
     83     mov esi, TASK_A_STACK32_SEGMENT
     84     mov edi, TASK_A_STACK32_DESC
     85     
     86     call InitDescItem
     87     
     88     ; initialize GDT pointer struct
     89     mov eax, 0
     90     mov ax, ds
     91     shl eax, 4
     92     add eax, GDT_ENTRY
     93     mov dword [GdtPtr + 2], eax
     94 
     95     ; 1. load GDT
     96     lgdt [GdtPtr]
     97     
     98     ; 2. close interrupt
     99     cli 
    100     
    101     ; 3. open A20
    102     in al, 0x92
    103     or al, 00000010b
    104     out 0x92, al
    105     
    106     ; 4. enter protect mode
    107     mov eax, cr0
    108     or eax, 0x01
    109     mov cr0, eax
    110     
    111     ; 5. jump to 32 bits code
    112     jmp dword Code32Selector : 0
    113 
    114     
    115 ; esi    --> code segment label
    116 ; edi    --> descriptor label
    117 InitDescItem:
    118     push eax
    119     
    120     mov eax, 0
    121     mov ax, cs
    122     shl eax, 4
    123     add eax, esi
    124     mov word [edi + 2], ax
    125     shr eax, 16
    126     mov byte [edi + 4], al
    127     mov byte [edi + 7], ah
    128     
    129     pop eax
    130     
    131     ret
    132      
    133 [section .dat]
    134 [bits 32]
    135 DATA32_SEGMENT:
    136     DTOS               db   "D.T.OS!", 0
    137     DTOS_OFFSET        equ  DTOS - $$
    138     
    139 Data32SegLen   equ  $ - DATA32_SEGMENT
    140 
    141 
    142 [section .s32]
    143 [bits 32]
    144 CODE32_SEGMENT:
    145     mov ax, VideoSelector
    146     mov gs, ax
    147     
    148     mov ax, Data32Selector
    149     mov ds, ax
    150     
    151     mov ax, Stack32Selector
    152     mov ss, ax
    153     
    154     mov eax, TopOfStack32
    155     mov esp, eax
    156     
    157     mov ebp, DTOS_OFFSET
    158     mov bx, 0x0c
    159     mov dh, 12
    160     mov dl, 33
    161     
    162     call FunctionSelector : PrintString
    163     
    164     mov ax, TaskALdtSelector
    165     
    166     lldt ax
    167     
    168     push TaskAStack32Selector
    169     push TaskATopOfStack32
    170     push TaskACode32Selector
    171     push 0
    172     retf
    173     
    174     jmp $
    175 
    176 Code32SegLen    equ    $ - CODE32_SEGMENT
    177 
    178 [section .gs]
    179 [bits 32]
    180 STACK32_SEGMENT:
    181     times 1024 * 4 db 0
    182     
    183 Stack32SegLen   equ $ - STACK32_SEGMENT
    184 TopOfStack32    equ Stack32SegLen - 1
    185 
    186 
    187 ; ======================================
    188 ;
    189 ;      Global Function Segment
    190 ;
    191 ; ======================================
    192 
    193 [section .func]
    194 [bits 32]
    195 FUNCTION_SEGMENT:
    196 
    197 ; ds:ebp     -->    string  address
    198 ; bx         -->    attribute
    199 ; dx         -->    dh : row, dl : col
    200 PrintStringFunc:
    201     push ebp
    202     push eax
    203     push edi 
    204     push cx
    205     push dx
    206     
    207 print:
    208     mov cl, [ds:ebp]
    209     cmp cl, 0
    210     je end
    211     mov eax, 80
    212     mul dh
    213     add al, dl
    214     shl eax, 1
    215     mov edi, eax
    216     mov ah, bl
    217     mov al, cl
    218     mov [gs:edi], ax
    219     inc ebp
    220     inc dl
    221     jmp print
    222     
    223 end:
    224     pop dx
    225     pop cx
    226     pop edi
    227     pop eax
    228     pop ebp
    229     
    230     retf
    231     
    232 PrintString       equ    PrintStringFunc - $$
    233 
    234 FunctionSegLen    equ    $ - FUNCTION_SEGMENT
    235 
    236 ; ==================================
    237 ;        
    238 ;        Task A Code Segment
    239 ;
    240 ;===================================
    241 [section .task-a-ldt]
    242 ; Task A LDT definition
    243 ;                                ¶Î»ùÖ·         ¶ÎœçÏÞ                ¶ÎÊôÐÔ
    244 
    245 TASK_A_LDT_ENTRY:
    246 TASK_A_CODE32_DESC  : Descriptor   0,    TaskACode32SegLen - 1,  DA_C + DA_32 + DA_DPL3
    247 TASK_A_DATA32_DESC  : Descriptor   0,    TaskAData32SegLen - 1,  DA_DR + DA_32 + DA_DPL3
    248 TASK_A_STACK32_DESC : Descriptor   0,    TaskAStack32SegLen - 1, DA_DRW + DA_32 + DA_DPL3
    249 
    250 TaskALdtLen        equ   $ - TASK_A_LDT_ENTRY
    251 
    252 ; Task A LDT  Selector
    253 TaskACode32Selector        equ  (0x0000 << 3) + SA_TIL + SA_RPL3
    254 TaskAData32Selector     equ     (0x0001 << 3) + SA_TIL + SA_RPL3
    255 TaskAStack32Selector    equ  (0x0002 << 3) + SA_TIL + SA_RPL3
    256 
    257 [section .task-a-dat]
    258 [bits 32]
    259 TASK_A_DATA32_SEGMENT:
    260     TASK_A_STRING        db   "This is Task A", 0
    261     TASK_A_STRING_OFFSET    equ     TASK_A_STRING - $$
    262     
    263 TaskAData32SegLen    equ $ - TASK_A_DATA32_SEGMENT
    264 
    265 [section .task-a-gs]
    266 [bits 32]
    267 TASK_A_STACK32_SEGMENT:
    268     times 1024 db 0
    269     
    270 TaskAStack32SegLen    equ     $ - TASK_A_STACK32_SEGMENT
    271 TaskATopOfStack32    equ     TaskAStack32SegLen - 1
    272 
    273 [section .task-a-s32]
    274 [bits 32]
    275 TASK_A_CODE32_SEGMENT:
    276     mov ax, TaskAData32Selector
    277     mov ds, ax
    278     
    279     jmp $
    280     
    281 
    282 TaskACode32SegLen   equ  $ - TASK_A_CODE32_SEGMENT

    第10-16行我们定义的段描述符特权级都是0,处理器从实模式跳转到保护模式后进入的是核心特权级0,进入32位的保护模式后首先执行的是144行的程序,我们首先将一些段选择子放在段寄存器中,157-162行调用了函数进行打印,这个FUNCTION_SEGMENT段也是在特权级0,所以这时候的打印不涉及特权级的转移。

    164-166行将任务段的选择子加载进CPU的特殊寄存器中,168-170将任务段的栈段选择子、栈顶地址、任务段的代码段选择子压入高特权级的栈中,第171行压入的0指的是偏移地址,第172行的retf远跳转返回的作用是使处理器从核心特权级0跳转到普通特权级3。跳转的时候处理器会自动的在核心态的栈中加载我们刚刚存进去的值到相应的寄存器中,然后程序就到了275行的任务段中的代码段执行。

    为了单步执行我们先使用如下命令对loader可执行程序进行反编译:

    ndisasm -b 32 -o 0x9000 loader > loader.txt          

    -b 32是以32位的方式进行反编译。

    在反编译得到文件中我们找到lldt所在的位置,断点就打在这里:

     

    启动bochs,使用break 0x915D打上断点。

    输入c执行到断点处,结果如下:

    可以看到下一条指令就是 lldt ax,继续单步执行:

    单步执行并使用sreg查看寄存器信息,可以看到cs中的值是0x0008,可知最后两位是00,这时处于核心特权级0。

    继续单步执行:

    retf执行完之后再次使用retf查看寄存器的值,可以看到cs的之变成了0x0007,最后两位是11,这说明特权级变为了3。

    继续单步执行:

    程序转移到了276行的地方。

    继续进行实验,我们我特权级3模拟一个内核函数调用,这就涉及到了低特权级到高特权级的转移,初步给出程序如下:

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

    第19行添加了调用门的描述符,偏移位置是PrintString,第39行添加了调用门的选择子。

    然后我们在TASKA任务段模拟内核函数的调用,也就是在第281行这里开始,先将任务段中的数据段加载进数据段寄存器ds。

    第284行将字符串的偏移放到ebp寄存器里面,这相当于先在用户空间把参数准备好,第289行即通过调用门执行了这个调用,但是实验结果显示,程序崩溃了。

    这是为什么呢?

    特权级转移的时候栈会变化。

    因为从低特权级到高特权级的跳转需要将栈切换到高特权级的栈,这个高特权级的栈去哪里找呢?去TSS段里面去找,这个段里面保存了栈的一些信息,但是现在我们的TSS并没有准备好,所以出错了,对程序进行改进。

    TSS段本质也是一段内存。

    改进的程序如下:

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

    TSS段本质也是一段内存,因此在44-59行我们定义了这个段,在这个段中,我们只定义了特权级0的栈的信息,特权级1和2的栈的信息赋值为0。

    第17行定义了这个段的段描述符,第38行定义了这个段的选择子。

    此外第20行的调用门的描述符的DPL要定义成3。

    第40行的调用门的选择子的RPL也要定义成3。

    在程序运行的时候不要忘了TSS段的段基址的初始化,这是在113-116行完成的。

    在程序还在核心态特权级0的时候,还要将TSS加载进处理器内部的特殊寄存器中,194-196正是完成了这个操作,用到的指令时ltr。

    进行完这些修改之后,我们再次执行程序,发现程序还是崩溃,进行单步执行操作:

    首先使用如下指令进行反汇编:

    ndisasm -b 32 -o 0x9000 loader > loader.txt

    找到lldt后面的那个retf所在的位置:

    位置为0x92DB。

    打断点再次单步执行:

    上图中马上要经过调用门了,继续单步执行:

    通过调用门调用之后可以看到cs的值为0x0028,最后两位是00,到了核心态特权级0。

    调用门之后程序到了232行的PrintStringFunc处,继续单步执行:

    在第250行的程序之前程序还没有出错,继续单步执行第250行:

    这时候程序崩溃了,产生了上图中的错误。

    第250行的程序的本质是内存赋值,即从ax指向的内存复制到gs代表的内存,ax代表的内存由DS寄存器获得,上图中可以看到DS的rpl为3,而GS的rpl为0,这相当于从用户态向内核态赋值数据,这是一个很危险的操作,错误就出在了这里。

     为了解决这个错误,我们将Vedio段描述符的dpl改为3:

    选择子的rpl也改为3:

    再次执行程序结果如下:

    程序可以正常的执行了。

     RPL究竟是什么?有什么用?

    RPL的意义:

      位置意义:

        选择子或者段寄存器的最低两位。

      请求意义:

        资源请求的特权级(不同于当前特权级CPL)。

    请求特权级表明了,请求这个资源的时候所使用的特权级是什么。

    如果当前执行的代码段的CPL为0,那么是不是就可以访问任意的内存了呢?

    这时候还取决于资源的请求特权级也即RPL,即使这时候CPL为0,但是如果RPL很低也是不能请求对应的资源的。

    资源请求时:

    CPL、RPL、DPL共同确定请求是否合法。

    当前代码(CPL)-> 选择子(RPL) ->  数据段(DPL)。

    小结:

    TSS是通过调用门转移到高特权级的关键。

    TSS是处理器的硬件数据结构,用于实现多任务。

    TSS的结构遵循保护模式下的内存使用规则。

    RPL在请求资源时是合法性判断的依据之一。

    处理器使用CPL、RPL、DPL共同确定合法性。

    参考:狄泰软件学院唐佐林操作系统教程

  • 相关阅读:
    用c#写一个json的万能解析器
    使用Xpath从网页中获取数据
    pdf文件流生成pdf文件
    AES加密和Base64混合加密
    参数请求post, get , delete中的基本使用(2)
    参数请求post, get , delete中的基本使用(1)
    java多线程打印ABC
    我的开发工具
    MyBatis的#与$
    struts1
  • 原文地址:https://www.cnblogs.com/wanmeishenghuo/p/9782418.html
Copyright © 2011-2022 走看看