在全局描述符表中创建非重叠段

时间:2016-12-09 20:05:22

标签: assembly x86 nasm bootloader protected-mode

在这个引导程序中,我试图为内核代码和用户代码设置单独的全局描述符表条目(尽管有一些简化,请参阅注释)。创建不相交的段会导致三重错误,即使这些段具有相同的权限级别(环0)。

以下代码按预期运行。它定义了单个代码段和单个数据段,因此不提供保护。源文件的1024个字节被写入虚拟软盘,因此"软盘"这是"这个文件的同义词"。

;***BEGIN SECTOR 1 OF FLOPPY***
BITS 16
ORG 0x7C00              ; standard bootloader location

main:   
    CLI             
    XOR AX, AX          ; zero the segments (relative to ORG)
    MOV DS, AX
    MOV ES, AX
    MOV AX, 0x9000          ; stack begins at 0x9000-0xFFFF
    MOV SS, AX
    MOV SP, 0xFFFF
    STI             

; Load the second sector of this floppy into memory at 0x07C0:0x0200 (deliberately lacks error checking)
    MOV AH, 0x02       ; BIOS INT 0x13 "read sector" function
    MOV AL, 1          ; Number of sectors to read
    MOV CH, 0          ; Cylinder/track
    MOV CL, 2          ; Sector of floppy to read
    MOV DH, 0          ; Head
    MOV DL, 0          ; Disk number (here, the floppy disk) (unnecessary since DL defaults to boot disk)
    MOV BX, 0x07C0     ; Segment containing the destination buffer (i.e. the current segment)
    MOV ES, BX
    MOV BX, 0x0200     ; Destination buffer offset
    INT 0x13

    CALL installGdt        ; Create the global descriptor table and load its pointer into GDTR

    CLI
    MOV EAX, CR0
    OR EAX, 1
    MOV CR0, EAX
    JMP 0x08:protected_mode



; Offset 0 in GDT: Descriptor code=0x00
gdt_data: 
    DD 0                ; null descriptor
    DD 0 

; Offset 8 bytes from start of GDT: descriptor code 0x08
; kernel code:              
    DW 0xFFFF           ; bits 0-15 (segment limit)
    DW 0x0000           ; bits 16-31 (low 2 bytes of base address)
    DB 0x00             ; bits 32-39 (middle byte of base address)
    DB 10011010B        ; bits 40-47 ("segment in memory" bit, privilege bits, descriptor bit, descriptor type, virtual memory access bit)
    DB 01000000B        ; bits 48-55 (granularity, segment type, bits 16-19 of segment limit)
    DB 0x00             ; bits 56-63 (high byte of base address)

; Offset 16 bytes from start of GDT: descriptor code 0x10
; kernel data:              
    DW 0xFFFF           ; bits 0-15 (segment limit)
    DW 0x0000           ; bits 16-31 (low 2 bytes of base address)
    DB 0x00             ; bits 32-39 (middle byte of base address)
    DB 10010010B        ; bits 40-47 ("segment in memory" bit, privilege bits, descriptor bit, descriptor type, virtual memory access bit)
    DB 01000000B        ; bits 48-55 (granularity, segment type, bits 16-19 of segment limit)
    DB 0x00             ; bits 56-63 (high byte of base address)

end_of_gdt:
gdt_description: 
    DW end_of_gdt - gdt_data - 1    ; size of GDT minus 1 (for GDTR)
    DD gdt_data             ; base of GDT




installGdt:
    CLI         
    PUSHA
    LGDT [gdt_description]      
    STI
    POPA
    RET

times 510-($-$$) DB 0       ; pad rest of sector
DW 0xAA55           ; add bootloader signature
;***END SECTOR 1 OF FLOPPY***



;***BEGIN SECTOR 2 OF FLOPPY***
BITS 32
protected_mode:
    MOV     AX, 0x10        ; set data segments to kernel data
    MOV     DS, AX
    MOV     SS, AX
    MOV     ES, AX
    MOV     ESP, 0x90000        ; stack begins from 0x90000

    MOV EAX, 5              ; a test to use in qemu register dump, to see if code reached this point
    JMP $



times 1024-($-$$) DB 0      ; pad rest of sector
;***END SECTOR 2 OF FLOPPY***

另一方面,当更改为以下时,会导致三重故障。请注意,我希望第二个扇区在0x07C0:0x0200加载到内存中,所以我将内核段的限制设置为0x01FF,而用户段从0x0200开始。

;***BEGIN SECTOR 1 OF FLOPPY***
BITS 16
ORG 0x7C00              ; standard bootloader location

main:   
    CLI             
    XOR AX, AX          ; zero the segments (relative to ORG)
    MOV DS, AX
        MOV ES, AX
        MOV AX, 0x9000          ; stack begins at 0x9000-0xFFFF
    MOV SS, AX
    MOV SP, 0xFFFF
    STI             

; Load the second sector of this floppy into memory at 0x07C0:0x0200 (deliberately lacks error checking)
    MOV AH, 0x02       ; BIOS INT 0x13 "read sector" function
    MOV AL, 1          ; Number of sectors to read
    MOV CH, 0          ; Cylinder/track
    MOV CL, 2          ; Sector of floppy to read
    MOV DH, 0          ; Head
    MOV DL, 0          ; Disk number (here, the floppy disk) (unnecessary since DL defaults to boot disk)
    MOV BX, 0x07C0     ; Segment containing the destination buffer (i.e. the current segment)
    MOV ES, BX
    MOV BX, 0x0200     ; Destination buffer offset
    INT 0x13

    CALL installGdt        ; Create the global descriptor table in RAM

    CLI
    MOV EAX, CR0
    OR EAX, 1
    MOV CR0, EAX
    JMP 0x18:protected_mode



; Offset 0 in GDT: Descriptor code=0x00
gdt_data: 
    DD 0                ; null descriptor
    DD 0 

; Offset 8 bytes from start of GDT: descriptor code 0x08
; kernel code:              
    DW 0x01FF           ; bits 0-15 (segment limit)
    DW 0x0000           ; bits 16-31 (low 2 bytes of base address)
    DB 0x00             ; bits 32-39 (middle byte of base address)
    DB 10011010B        ; bits 40-47 ("segment in memory" bit, privilege bits, descriptor bit, descriptor type, virtual memory access bit)
    DB 01000000B        ; bits 48-55 (granularity, segment type, bits 16-19 of segment limit)
    DB 0x00             ; bits 56-63 (high byte of base address)

; Offset 16 bytes from start of GDT: descriptor code 0x10
; kernel data:              
    DW 0x01FF           ; bits 0-15 (segment limit)
    DW 0x0000           ; bits 16-31 (low 2 bytes of base address)
    DB 0x00             ; bits 32-39 (middle byte of base address)
    DB 10010010B        ; bits 40-47 ("segment in memory" bit, privilege bits, descriptor bit, descriptor type, virtual memory access bit)
    DB 01000000B        ; bits 48-55 (granularity, segment type, bits 16-19 of segment limit)
    DB 0x00             ; bits 56-63 (high byte of base address)

; Descriptor code 0x18
; user code:                ; (see immediately above for descriptions of bit fields)
    DW 0xFFFF           ; bits 0-15 
    DW 0x0200           ; bits 16-31 
    DB 0x00             ; bits 32-39 
    DB 10011010B        ; bits 40-47 (privilege set to ring 0 for simplicity)
    DB 01000000B        ; bits 48-55 
    DB 0x00             ; bits 56-63 

; Descriptor code 0x20
; user data:                ; (see immediately above for descriptions of bit fields)
    DW 0xFFFF           ; bits 0-15 
    DW 0x0200           ; bits 16-31 
    DB 0x00             ; bits 32-39 
    DB 10010010B        ; bits 40-47 (privilege set to ring 0 for simplicity)
    DB 01000000B        ; bits 48-55 
    DB 0x00             ; bits 56-63 

end_of_gdt:
gdt_description: 
    DW end_of_gdt - gdt_data - 1    ; size of GDT minus 1 (for GDTR)
    DD gdt_data             ; base of GDT




installGdt:
    CLI         
    PUSHA
    LGDT [gdt_description]      
    STI
    POPA
    RET

times 510-($-$$) DB 0       ; pad rest of sector
DW 0xAA55           ; add bootloader signature
;***END SECTOR 1 OF FLOPPY***



;***BEGIN SECTOR 2 OF FLOPPY***
BITS 32
protected_mode:
    MOV     AX, 0x20        ; set data segments to user data
    MOV     DS, AX
    MOV     SS, AX
    MOV     ES, AX
    MOV     ESP, 0x90000        ; stack begins from 0x90000

    MOV EAX, 5              ; a test to use in qemu register dump, to see if code reached this point
    JMP $



times 1024-($-$$) DB 0      ; pad rest of sector
;***END SECTOR 2 OF FLOPPY***

0 个答案:

没有答案