2016-11-20 6 views
1

Qemuでx86アーキテクチャでページングを有効にしようとしています。
しかし、このコードは3重の障害になります。x86でページングを有効にするQemu

このコードセグメントは保護モードで実行されます。
コード:https://github.com/mridulv/simpleOperatingSystem

これはカーネルのエントリは、このページのディレクトリ、テーブルを作成したカーネルファイルである

[bits 32] 

[extern main] 
[extern main2] 
[extern page_table] 

call main 

lea ECX, [page_table - 0xC0000000] 
mov CR3, ECX 

mov ECX, CR0 
or ECX, 0x80000000 
mov CR0, ECX 

;lea ECX, [StartInHigherHalf] 
;jmp ECX 

;StartInHigherHalf: 
; call main2 

jmp $ 

ファイルです。

unsigned int page_table[1024] __attribute__((aligned(4096)));; 

void set_page_tables() { 
    unsigned int pages_entry[1024 * 1024] __attribute__((aligned(4096))); 

    unsigned int KERNEL_VIRTUAL_OFFSET = 0xC0000000; 
    unsigned int KERNEL_FIRST_VIRTUAL_ADDRESS = 0xC0000000 >> 12; 

    int numPageTables = 4; 
    int numPagesInPageTable = 1024; 
    int numPageTableEntriesInPageDirectory = 1024; 
    int totalPages = numPageTables * numPagesInPageTable; 

    unsigned int index = 0; 
    unsigned int *pages_ptr = (unsigned int *)(pages_entry - KERNEL_VIRTUAL_OFFSET); 
    unsigned int *page_table_ptr = (unsigned int *)(pages_entry - KERNEL_VIRTUAL_OFFSET); 

    unsigned int positionAndFlags = 7; 

    while (index < totalPages) { 
     pages_ptr[index] = positionAndFlags; 
     index = index + 1; 
     positionAndFlags += 4096; 
    } 

    positionAndFlags = 7; 
    index = KERNEL_FIRST_VIRTUAL_ADDRESS; 
    unsigned int totalPagesLeft = KERNEL_FIRST_VIRTUAL_ADDRESS + totalPages; 
    while (index < totalPagesLeft) { 
     pages_ptr[index] = positionAndFlags; 
     index = index + 1; 
     positionAndFlags += 4096; 
    } 

    positionAndFlags = (unsigned int)&pages_ptr[0]; 
    positionAndFlags = positionAndFlags | 7; 
    index = 0; 
    while (index < numPageTableEntriesInPageDirectory) { 
     page_table_ptr[index] = positionAndFlags; 
     index = index + 1; 
     positionAndFlags += 4096; 
    } 
} 

void main() { 
    char* video_memory = (char*) 0xb8000; 
    *video_memory = 'X'; 
    set_page_tables(); 
} 

void main2() { 
    char* video_memory = (char*) 0xb8004; 
    *video_memory = 'Y'; 
    // __asm__ 
    // (
    // "leal (page_table,), %ecx\n\t" // 0xC0000000 = KERNEL_VIRTUAL_BASE 
    // "movl %cr3, %ecx" 
    //); 
} 

Linker.ld

SECTIONS { 
    . = 0xC0100000; 

    .text : AT(ADDR(.text) - 0xC0000000) { 
     *(.text); 
    } 

    . = ALIGN(0x1000); 
    .bss : AT(ADDR(.bss) - 0xC0000000) { 
     *(.text); 
    } 

    . = ALIGN(0x1000); 
    .data : AT(ADDR(.data) - 0xC0000000) { 
     *(.text); 
    } 
} 
+0

明らかなことがいくつかあります。私が知る[A20 line](http://wiki.osdev.org/A20_Line)は有効にしていません。 'boot.asm'では、起動時に_DL_(ブートドライブ)を保存し、直後にデータ(' PROTECTED_MODE_STR'と 'BEGIN_STR')を配置します。 CPUはデータの実行を試みます。データをすべてのコードの後ろに置きます(ブート署名の直前に移動してみてください)。別の大きな問題は、カーネルをメモリー上の0x1000にロードすることです。リンカースクリプトは '0xC0100000'のベースを使用します。これはあなたのカーネルが0x100000でロードされたものと仮定していますが、あなたは0x1000にあります。したがって、あなたの場合は、 '0xC0001000'が必要になるかもしれません。 –

+0

私はそれ以上に見ていません。しかし、ページングを有効にしようとするコードに到達する前に十分な問題があります。 –

+0

'lea ECX、[page_table - 0xC0000000]'を 'mov ECX、page_table - 0xC0000000'に変更することもお勧めします –

答えて

0

私は物事を明確にするために、あなたのコードの上部にあるセクションの宣言を追加するようにアドバイスう -

section .text 

とあなたの中のエラーコードは実行前のものです

call main 

あなたのコードはESPレジスタを埋めてスタックをセットアップしません。これを行うには

、あなたのコードは次のように一定の 'STACK_SIZE' を作成し

  1. ようにする必要があります -

    STACK_SIZE equ <valueOfSizeOfStack> 
    
  2. スタック用

    section .bss 
    kernelStack: RESB <valueOfSizeOfStack> 
    
をスペースを作成します。

"valueOfSi zeOfStack "フィールドにスタックの4096(4-KB)またはその倍数(バイナリサイズでカウントされます)を追加できます。

+0

GitHubで、私が作成している完全なカーネルの例について、CircuitKernelを検索してください。 –

関連する問題