📄 st32_64.asm
字号:
cli
mov ax,0b800h
mov es,ax
mov byte ptr es:[164],'c'
mov ax,cs
mov es,ax
lea eax, OffsetIn32BitProtectedMode
add eax, 20000h + 6h
mov dword ptr[OffsetIn32BitProtectedMode], eax
lea eax, OffsetInLongMode
add eax, 20000h + 6h
mov dword ptr[OffsetInLongMode], eax
;
; load GDT
;
db 66h
lgdt fword ptr [gdtr]
;
; Enable Protect Mode (set CR0.PE=1)
;
mov eax, cr0 ; Read CR0.
or eax, 1h ; Set PE=1
mov cr0, eax ; Write CR0.
db 066h
db 0eah ; jmp far 16:32
OffsetIn32BitProtectedMode:
dd 00000000h ; offset $+8 (In32BitProtectedMode)
dw 10h ; selector (flat CS)
In32BitProtectedMode:
;
; Entering Long Mode
;
db 66h
mov ax, 8
mov ds, ax
mov es, ax
mov ss, ax
;
; Enable the 64-bit page-translation-table entries by
; setting CR4.PAE=1 (this is _required_ before activating
; long mode). Paging is not enabled until after long mode
; is enabled.
;
db 0fh
db 20h
db 0e0h
; mov eax, cr4
bts eax, 5
db 0fh
db 22h
db 0e0h
; mov cr4, eax
;
; This is the Trapolean Page Tables that are guarenteed
; under 4GB.
;
; Address Map:
; 10000 ~ 12000 - efildr (loaded)
; 20000 ~ 21000 - start64.com
; 21000 ~ 22000 - efi64.com
; 22000 ~ 90000 - efildr
; 90000 ~ 96000 - 4G pagetable (will be reload later)
;
db 0b8h
dd 90000h
; mov eax, 90000h
mov cr3, eax
;
; Enable long mode (set EFER.LME=1).
;
db 0b9h
dd 0c0000080h
; mov ecx, 0c0000080h ; EFER MSR number.
db 0fh
db 32h
; rdmsr ; Read EFER.
db 0fh
db 0bah
db 0e8h
db 08h
; bts eax, 8 ; Set LME=1.
db 0fh
db 30h
; wrmsr ; Write EFER.
;
; Enable paging to activate long mode (set CR0.PG=1)
;
mov eax, cr0 ; Read CR0.
db 0fh
db 0bah
db 0e8h
db 01fh
; bts eax, 31 ; Set PG=1.
mov cr0, eax ; Write CR0.
jmp GoToLongMode
GoToLongMode:
db 067h
db 0eah ; Far Jump $+9:Selector to reload CS
OffsetInLongMode:
dd 00000000 ; $+9 Offset is ensuing instruction boundary
dw 038h ; Selector is our code selector, 38h
InLongMode:
db 66h
mov ax, 30h
mov ds, ax
db 66h
mov ax, 18h
mov es, ax
mov ss, ax
mov ds, ax
db 0bdh
dd 400000h
; mov ebp,000400000h ; Destination of EFILDR32
db 0bbh
dd 70000h
; mov ebx,000070000h ; Length of copy
;
; load idt later
;
db 48h
db 33h
db 0c0h
; xor rax, rax
db 66h
mov ax, offset idtr
db 48h
db 05h
dd 20000h
; add rax, 20000h
db 0fh
db 01h
db 18h
; lidt fword ptr [rax]
db 48h
db 0c7h
db 0c0h
dd 21000h
; mov rax, 21000h
db 50h
; push rax
; ret
db 0c3h
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 ; Selector [0x0]
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 ; Selector [0x8]
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 ; Selector [0x10]
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 ; Selector [0x18]
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 ; Selector [0x20]
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 ; Selector [0x28]
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
;
; system data segment descriptor
;
SYS_DATA64_SEL equ $-GDT_BASE ; Selector [0x30]
dw 0FFFFh ; limit 0xFFFFF
dw 0 ; base 0
db 0
db 092h ; P | DPL [1..2] | 1 | 1 | C | R | A
db 0CFh ; G | D | L | AVL | Segment [19..16]
db 0
;
; system code segment descriptor
;
SYS_CODE64_SEL equ $-GDT_BASE ; Selector [0x38]
dw 0FFFFh ; limit 0xFFFFF
dw 0 ; base 0
db 0
db 09Ah ; P | DPL [1..2] | 1 | 1 | C | R | A
db 0AFh ; G | D | L | AVL | Segment [19..16]
db 0
; spare segment descriptor
SPARE4_SEL equ $-GDT_BASE ; Selector [0x40]
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
dq 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_CODE64_SEL ; selector 15:0
db 0 ; 0 for interrupt gate
db 0eh OR 80h ; type = 386 interrupt gate, present
dw 0 ; offset 31:16
dd 0 ; offset 63:32
dd 0 ; 0 for reserved
; debug exception (INT 1)
DEBUG_EXCEPT_SEL equ $-IDT_BASE
dw 0 ; offset 15:0
dw SYS_CODE64_SEL ; selector 15:0
db 0 ; 0 for interrupt gate
db 0eh OR 80h ; type = 386 interrupt gate, present
dw 0 ; offset 31:16
dd 0 ; offset 63:32
dd 0 ; 0 for reserved
; NMI (INT 2)
NMI_SEL equ $-IDT_BASE
dw 0 ; offset 15:0
dw SYS_CODE64_SEL ; selector 15:0
db 0 ; 0 for interrupt gate
db 0eh OR 80h ; type = 386 interrupt gate, present
dw 0 ; offset 31:16
dd 0 ; offset 63:32
dd 0 ; 0 for reserved
; soft breakpoint (INT 3)
BREAKPOINT_SEL equ $-IDT_BASE
dw 0 ; offset 15:0
dw SYS_CODE64_SEL ; selector 15:0
db 0 ; 0 for interrupt gate
db 0eh OR 80h ; type = 386 interrupt gate, present
dw 0 ; offset 31:16
dd 0 ; offset 63:32
dd 0 ; 0 for reserved
; overflow (INT 4)
OVERFLOW_SEL equ $-IDT_BASE
dw 0 ; offset 15:0
dw SYS_CODE64_SEL ; selector 15:0
db 0 ; 0 for interrupt gate
db 0eh OR 80h ; type = 386 interrupt gate, present
dw 0 ; offset 31:16
dd 0 ; offset 63:32
dd 0 ; 0 for reserved
; bounds check (INT 5)
BOUNDS_CHECK_SEL equ $-IDT_BASE
dw 0 ; offset 15:0
dw SYS_CODE64_SEL ; selector 15:0
db 0 ; 0 for interrupt gate
db 0eh OR 80h ; type = 386 interrupt gate, present
dw 0 ; offset 31:16
dd 0 ; offset 63:32
dd 0 ; 0 for reserved
; invalid opcode (INT 6)
INVALID_OPCODE_SEL equ $-IDT_BASE
dw 0 ; offset 15:0
dw SYS_CODE64_SEL ; selector 15:0
db 0 ; 0 for interrupt gate
db 0eh OR 80h ; type = 386 interrupt gate, present
dw 0 ; offset 31:16
dd 0 ; offset 63:32
dd 0 ; 0 for reserved
; device not available (INT 7)
DEV_NOT_AVAIL_SEL equ $-IDT_BASE
dw 0 ; offset 15:0
dw SYS_CODE64_SEL ; selector 15:0
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -