Assembly 进入长模式
我一直在工作的引导加载程序,目前正试图让它切换到长模式。到目前为止,我已经切换到保护模式,我确信它可以工作,但当我启用分页进入长模式时,似乎会导致故障。我想这可能是因为我的页面表。代码如下:Assembly 进入长模式,assembly,x86,nasm,bootloader,osdev,Assembly,X86,Nasm,Bootloader,Osdev,我一直在工作的引导加载程序,目前正试图让它切换到长模式。到目前为止,我已经切换到保护模式,我确信它可以工作,但当我启用分页进入长模式时,似乎会导致故障。我想这可能是因为我的页面表。代码如下: [BITS 16] org 0x2000 Start: jmp main ;Constants %DEFINE TEAL 0x03 %DEFINE RED 0x04 %DEFINE PURPLE 0x05 %DEFINE VIDEO_MEM 0xB8000 %DEFINE COL
[BITS 16]
org 0x2000
Start:
jmp main
;Constants
%DEFINE TEAL 0x03
%DEFINE RED 0x04
%DEFINE PURPLE 0x05
%DEFINE VIDEO_MEM 0xB8000
%DEFINE COLS 80 ; width and height of screen
%DEFINE LINES 25
%DEFINE LONG_SELECTOR 3 << 3
X_POS: db 0
Y_POS: db 0
;Enabling the A20 line
EnableA20:
IN AL, 0x92 ; A20, using fast A20 gate
MOV CL, AL
AND CL, 2
JNZ .skip ; if a20 bit seems set, don't touch it
OR AL, 2
OUT 0x92, AL
.skip:
ret
main:
;first stage of bootloader is loaded at the address 0x07c0:0
;second stage of bootloader is loaded at address 0x200:0x0
cli
xor ax, ax ; All segments set to 0, flat memory model
mov ds, ax
mov es, ax
mov gs, ax
mov fs, ax
mov ss, ax
; Set stack top SS:0xffff
mov sp, 0x0FFFF
mov [CDDriveNumber], dl
SwitchToProtectedMode:
lgdt [GDT_32];load the gdt
call EnableA20
mov eax, cr0
or eax, 1
mov cr0, eax
; Flush CS and set code selector
jmp 0x8:Protected_Mode
[BITS 32];Declare 32 bits
Protected_Mode:
mov eax,0x10 ; load 4 GB data descriptor
mov ds,ax ; to all data segment registers
mov es,ax
mov fs,ax
mov gs,ax
mov ss,ax
mov eax,cr4
or eax,1 << 5
mov cr4,eax ; enable physical-address extensions
mov edi,70000h
mov ecx,4000h >> 2
xor eax,eax
rep stosd ; clear the page tables
mov dword [70000h],71000h + 111b ; first PDP table
mov dword [71000h],72000h + 111b ; first page directory
mov dword [72000h],73000h + 111b ; first page table
mov edi,73000h ; address of first page table
mov eax,0 + 111b
mov ecx,256 ; number of pages to map (1 MB)
make_page_entries:
stosd
add edi,4
add eax,1000h
loop make_page_entries
mov eax,70000h
mov cr3,eax ; load page-map level-4 base
mov ecx,0C0000080h ; EFER MSR
rdmsr
or eax,1 << 8 ; enable long mode
wrmsr
lgdt[GDT_64]
mov eax,cr0 ; << problem here
or eax,1 << 31
mov cr0,eax ; enable paging
jmp 0x08:Long_Mode
[BITS 64]
Long_Mode:
call clear
xor bx, bx
mov bx, Entered_LMODE
call sPrint
cli
hlt
[BITS 32]
clear:
pusha
mov edi, VIDEO_MEM
mov BYTE[edi], ' '
mov BYTE[edi+1], TEAL
rep stosw
MOV BYTE[X_POS], 0x0
MOV BYTE [Y_POS], 0x0
popa
ret
sPrint:
pusha
jmp .start
.Row:
call NewLine
MOV BYTE[EDI], ' '
jmp .Next
.start:
MOV EDI, VIDEO_MEM
xor ecx, ecx
xor eax, eax
mov ecx, COLS*2 ; Mode 7 has 2 bytes per char, so its COLS*2 bytes per line
mov al, BYTE [Y_POS] ; get y pos
mul ecx ; multiply y*COLS
push eax ; save eax--the multiplication
mov al, byte [X_POS] ; multiply _CurX by 2 because it is 2 bytes per char
mov cl, 2
mul cl
pop ecx ; pop y*COLS result
add eax, ecx
add edi, eax
mov al,BYTE[bx]
cmp al, 0x0;check if end
je .Done
cmp al, 0xA;check if new line
je .Row
mov BYTE[edi],al
.Next:
mov BYTE[edi+1], PURPLE
INC BX
inc BYTE[X_POS] ; go to next character
cmp BYTE[X_POS], COLS ; are we at the end of the line?
je .Row ; yep-go to next row
jmp .start
.Done:
popa
ret
NewLine:
inc BYTE[Y_POS]
MOV BYTE[X_POS], -1
ret
Entered_PMODE: db "You have succcessfully entered Protected Mode Very Happy",0xA, 0
LOAD_SUCCESS: db "Stage 2 Loaded Successfully",0xA, 0
CDDriveNumber: db 0
Entered_LMODE: db "You have successfully entered Long Mode Very Happy !!!!!!!!!!!",0xA,0
GDT_START:
;null descriptor
dd 0
dd 0
;data descriptor
dw 0xFFFF
dw 0
db 0
db 10011010b
db 11001111b
db 0
;code descriptor
dw 0xFFFF
dw 0
db 0
db 10010010b
db 11001111b
db 0
GDT_END:
align 4
GDT_32:
dw GDT_END - GDT_START - 1
dd GDT_START
GDT_64:
.Null:
dq 0x0000000000000000 ; Null Descriptor - should be present.
.Code_64:
dq 0x0020980000000000 ; 64-bit code descriptor.
dq 0x0000900000000000 ; 64-bit data descriptor.
.Pointer:
dw $ - GDT_64 - 1 ; 16-bit Size (Limit) of GDT.
dd GDT_64 ; 32-bit Base Address of GDT. (CPU will zero extend to 64-bit)
ALIGN 4
IDT:
.Length dw 0
.Base dd 0
PML4_POINTER:;blank table
dd 0
PML4_POINTER_END:
table_768: dd 0
[位16]
组织0x2000
开始:
jmp主
;常数
%定义TEAL 0x03
%定义红色0x04
%定义紫色0x05
%定义视频存储0xB8000
%定义cols80;屏幕的宽度和高度
%定义第25行
%定义长选择器3您需要使用lgdt[GDT\u 64.Pointer]
。此外,您不能从64位代码中使用clear
和sPrint
。您是从硬盘驱动器或CD引导的,还是什么?因为它超过512字节,并且没有55 aa
BIOS签名。我建议安装并使用内置gdb存根来调试你的code.CD,这是第二阶段我使用bochs进行调试我认为这是我的页面表的问题你不想要完整的代码吗??