start16.asm

来自「EFI BIOS是Intel提出的下一代的BIOS标准。这里上传的Edk源代码是」· 汇编 代码 · 共 843 行 · 第 1/3 页

ASM
843
字号

        add ebx,01000h                      ; Source of EFI32
        mov dword ptr [JUMP+2],ebx
        add ebx,01000h
        mov esi,ebx                         ; Source of EFILDR32

        mov ax,0b800h
        mov es,ax
        mov byte ptr es:[162],'b'
        mov ax,cs
        mov es,ax

;
; Enable A20 Gate 
;

        mov ax,2401h                        ; Enable A20 Gate
        int 15h
        jnc A20GateEnabled                  ; Jump if it suceeded

;
; If INT 15 Function 2401 is not supported, then attempt to Enable A20 manually.
;

        call    Empty8042InputBuffer        ; Empty the Input Buffer on the 8042 controller
        jnz     Timeout8042                 ; Jump if the 8042 timed out
        out     DELAY_PORT,ax               ; Delay 1 uS
        mov     al,WRITE_DATA_PORT_CMD      ; 8042 cmd to write output port
        out     KBD_STATUS_PORT,al          ; Send command to the 8042
        call    Empty8042InputBuffer        ; Empty the Input Buffer on the 8042 controller
        jnz     Timeout8042                 ; Jump if the 8042 timed out
        mov     al,ENABLE_A20_CMD           ; gate address bit 20 on
        out     KBD_CONTROL_PORT,al         ; Send command to thre 8042
        call    Empty8042InputBuffer        ; Empty the Input Buffer on the 8042 controller
        mov     cx,25                       ; Delay 25 uS for the command to complete on the 8042
Delay25uS:
        out     DELAY_PORT,ax               ; Delay 1 uS
        loop    Delay25uS                       
Timeout8042:


A20GateEnabled:

;
; DISABLE INTERRUPTS - Entering Protected Mode
;

        cli                             

        mov ax,0b800h
        mov es,ax
        mov byte ptr es:[164],'c'
        mov ax,cs
        mov es,ax

        db      66h     
        lgdt    fword ptr [gdtr]
        db      66h     
        lidt    fword ptr [idtr]

        mov     eax,cr0
        or      al,1
        mov     cr0,eax

        mov eax,0008h                       ; Flat data descriptor
        mov ebp,000400000h                  ; Destination of EFILDR32
        mov ebx,000070000h                  ; Length of copy
        
JUMP:
; jmp far 0010:00020000
        db  066h
        db  0eah
        dd  000020000h
        dw  00010h

Empty8042InputBuffer:
        mov cx,0
Empty8042Loop:
        out     DELAY_PORT,ax               ; Delay 1us
        in      al,KBD_STATUS_PORT          ; Read the 8042 Status Port
        and     al,02h                      ; Check the Input Buffer Full Flag
        loopnz  Empty8042Loop               ; Loop until the input buffer is empty or a timout of 65536 uS
        ret

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; data
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

        align 02h

gdtr    dw GDT_END - GDT_BASE - 1   ; GDT limit
        dd 0                        ; (GDT base gets set above)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;   global descriptor table (GDT)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

        align 02h

public GDT_BASE
GDT_BASE:
; null descriptor
NULL_SEL            equ $-GDT_BASE
        dw 0            ; limit 15:0
        dw 0            ; base 15:0
        db 0            ; base 23:16
        db 0            ; type
        db 0            ; limit 19:16, flags
        db 0            ; base 31:24

; linear data segment descriptor
LINEAR_SEL      equ $-GDT_BASE
        dw 0FFFFh       ; limit 0xFFFFF
        dw 0            ; base 0
        db 0
        db 092h         ; present, ring 0, data, expand-up, writable
        db 0CFh                 ; page-granular, 32-bit
        db 0

; linear code segment descriptor
LINEAR_CODE_SEL equ $-GDT_BASE
        dw 0FFFFh       ; limit 0xFFFFF
        dw 0            ; base 0
        db 0
        db 09Ah         ; present, ring 0, data, expand-up, writable
        db 0CFh                 ; page-granular, 32-bit
        db 0

; system data segment descriptor
SYS_DATA_SEL    equ $-GDT_BASE
        dw 0FFFFh       ; limit 0xFFFFF
        dw 0            ; base 0
        db 0
        db 092h         ; present, ring 0, data, expand-up, writable
        db 0CFh                 ; page-granular, 32-bit
        db 0

; system code segment descriptor
SYS_CODE_SEL    equ $-GDT_BASE
        dw 0FFFFh       ; limit 0xFFFFF
        dw 0            ; base 0
        db 0
        db 09Ah         ; present, ring 0, data, expand-up, writable
        db 0CFh                 ; page-granular, 32-bit
        db 0

; spare segment descriptor
SPARE3_SEL  equ $-GDT_BASE
        dw 0            ; limit 0xFFFFF
        dw 0            ; base 0
        db 0
        db 0            ; present, ring 0, data, expand-up, writable
        db 0            ; page-granular, 32-bit
        db 0

; spare segment descriptor
SPARE4_SEL  equ $-GDT_BASE
        dw 0            ; limit 0xFFFFF
        dw 0            ; base 0
        db 0
        db 0            ; present, ring 0, data, expand-up, writable
        db 0            ; page-granular, 32-bit
        db 0

; spare segment descriptor
SPARE5_SEL  equ $-GDT_BASE
        dw 0            ; limit 0xFFFFF
        dw 0            ; base 0
        db 0
        db 0            ; present, ring 0, data, expand-up, writable
        db 0            ; page-granular, 32-bit
        db 0

GDT_END:

        align 02h



idtr            dw IDT_END - IDT_BASE - 1   ; IDT limit
        dd 0                        ; (IDT base gets set above)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;   interrupt descriptor table (IDT)
;
;   Note: The hardware IRQ's specified in this table are the normal PC/AT IRQ
;       mappings.  This implementation only uses the system timer and all other
;       IRQs will remain masked.  The descriptors for vectors 33+ are provided
;       for convenience.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

;idt_tag db "IDT",0     
        align 02h

public IDT_BASE
IDT_BASE:
; divide by zero (INT 0)
DIV_ZERO_SEL        equ $-IDT_BASE
        dw 0            ; offset 15:0
        dw SYS_CODE_SEL ; selector 15:0
        db 0            ; 0 for interrupt gate
        db 0eh OR 80h   ; type = 386 interrupt gate, present
        dw 0            ; offset 31:16

; debug exception (INT 1)
DEBUG_EXCEPT_SEL    equ $-IDT_BASE
        dw 0            ; offset 15:0
        dw SYS_CODE_SEL ; selector 15:0
        db 0            ; 0 for interrupt gate
        db 0eh OR 80h   ; type = 386 interrupt gate, present
        dw 0            ; offset 31:16

; NMI (INT 2)
NMI_SEL             equ $-IDT_BASE
        dw 0            ; offset 15:0
        dw SYS_CODE_SEL ; selector 15:0
        db 0            ; 0 for interrupt gate
        db 0eh OR 80h   ; type = 386 interrupt gate, present
        dw 0            ; offset 31:16

; soft breakpoint (INT 3)
BREAKPOINT_SEL      equ $-IDT_BASE
        dw 0            ; offset 15:0
        dw SYS_CODE_SEL ; selector 15:0
        db 0            ; 0 for interrupt gate
        db 0eh OR 80h   ; type = 386 interrupt gate, present
        dw 0            ; offset 31:16

; overflow (INT 4)
OVERFLOW_SEL        equ $-IDT_BASE
        dw 0            ; offset 15:0
        dw SYS_CODE_SEL ; selector 15:0
        db 0            ; 0 for interrupt gate
        db 0eh OR 80h   ; type = 386 interrupt gate, present
        dw 0            ; offset 31:16

; bounds check (INT 5)
BOUNDS_CHECK_SEL    equ $-IDT_BASE
        dw 0            ; offset 15:0
        dw SYS_CODE_SEL ; selector 15:0
        db 0            ; 0 for interrupt gate
        db 0eh OR 80h   ; type = 386 interrupt gate, present
        dw 0            ; offset 31:16

; invalid opcode (INT 6)
INVALID_OPCODE_SEL  equ $-IDT_BASE
        dw 0            ; offset 15:0
        dw SYS_CODE_SEL ; selector 15:0
        db 0            ; 0 for interrupt gate
        db 0eh OR 80h   ; type = 386 interrupt gate, present
        dw 0            ; offset 31:16

; device not available (INT 7)
DEV_NOT_AVAIL_SEL   equ $-IDT_BASE
        dw 0            ; offset 15:0
        dw SYS_CODE_SEL ; selector 15:0
        db 0            ; 0 for interrupt gate
        db 0eh OR 80h   ; type = 386 interrupt gate, present
        dw 0            ; offset 31:16

; double fault (INT 8)
DOUBLE_FAULT_SEL    equ $-IDT_BASE
        dw 0            ; offset 15:0
        dw SYS_CODE_SEL ; selector 15:0
        db 0            ; 0 for interrupt gate
        db 0eh OR 80h   ; type = 386 interrupt gate, present
        dw 0            ; offset 31:16

; Coprocessor segment overrun - reserved (INT 9)
RSVD_INTR_SEL1      equ $-IDT_BASE
        dw 0            ; offset 15:0
        dw SYS_CODE_SEL ; selector 15:0
        db 0            ; 0 for interrupt gate
        db 0eh OR 80h   ; type = 386 interrupt gate, present
        dw 0            ; offset 31:16

; invalid TSS (INT 0ah)
INVALID_TSS_SEL     equ $-IDT_BASE
        dw 0            ; offset 15:0
        dw SYS_CODE_SEL ; selector 15:0
        db 0            ; 0 for interrupt gate
        db 0eh OR 80h   ; type = 386 interrupt gate, present
        dw 0            ; offset 31:16

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?