2016-12-25 5 views
0

Так что я создаю простую ОС, и я запускаю ошибку, указанную выше при вызове кода ядра из загрузочного сектора. Я потратил несколько дней на борьбу и все еще в тупике.load_seg_reg (ES, 0xfffc): недопустимый сегмент при попытке запустить код ядра из загрузочного сектора

Код невозможен при вызове KERNEL_OFFSET. Я знаю, что он терпит неудачу, потому что я пытаюсь перейти к недействительному сегменту, но я не могу понять, как и где. Я также заметил, что на самом деле это не чтение диска. Мой код load_kernel запрашивает 10 секторов для чтения, но только, казалось, был прочитан. Программа может войти в защищенный режим и в состоянии загружать то, что мне нужно для загрузки с диска, несмотря на то, что поведение загрузки является странным.

Im также показывает мой make-файл, потому что я подозреваю, что, возможно, я не связал вещи должным образом. Я запускаю OSX btw так idk, если команды shell im im правильные.

Я был в этом несколько дней, любая помощь будет оценена по достоинству. Благодаря

boot_sector

; 
; A simple boot sector program. 
; BIOS stores the boot drive in DL 
; 
[org 0x7c00] 
[bits 16] 

mov [BOOT_DRIVE], dl  ; Move boot drive info to memory. 

; Setup stack to a position we know is free. 
mov bp, 0x9000 
mov sp, bp 

; Output a nice message. 
mov dx, REAL_MODE_MSG 
call PrintString16 

; Load the kernel. 
mov dx, [BOOT_DRIVE] 
call LoadKernel 

mov dx, LOADED_KERNEL_MSG 
call PrintString16 

; Switch to protected mode. 
; Note, we never break from Protected mode. 
call SwitchToProtectedMode 

jmp $ 

; Including some useful routines. 
%include "string_utils_16.s" 
%include "gdt.s" 
%include "string_utils.s" 
%include "load_kernel.s" 
%include "switch_to_pm.s" 

[bits 32] 
BeginProtectedMode: 
    mov edx, PROT_MODE_MSG 
    call PrintString 

    ; This call should, theoritecally, run the instructions we just loaded. 
    ; AKA, the C code. 
    ; KERNEL_OFFSET is defined in load_kernel.s 

    call KERNEL_OFFSET 
    jmp $ 


BOOT_DRIVE   db 0 
LOADED_KERNEL_MSG db "Loaded kernel with no errors!", 0 
REAL_MODE_MSG  db "Welcome! Started in 16-bit Real Mode!", 0 
PROT_MODE_MSG  db "Now running in 32-bit Protected Mode", 0 

times 510 -($ - $$) db 0 

dw 0xaa55 

switch_to_pm

[bits 16] 
SwitchToProtectedMode: 
    cli 
    lgdt [gdt_descriptor] 
    ; To actually switch to 32 bit mode, set LSB of cr0 to 1 
    ; Can't touch the cr0 register directly so gotta do it the hard way. 
    mov eax, cr0 
    or eax, 0x1 
    mov cr0, eax 
    ; Technically, after that last move instruction, we're in 32 bit mode BUT 
    ; the CPU may have been doing work in between all this, since, the CPU can do 
    ; certain things in parallel if its got different circuitry to do those things, 
    ; which it probably does. Few of the things the CPU could do in parallel is 
    ; fetch, decode and execute. We dont want the CPU to be fetching the next 
    ; instruction while our stuff is happening (those next things that will be 
    ; fetched probably wont work in 32 bit mode) and we want it to finish whatever 
    ; it is currently executing. so, we're going to do a far jump to 
    ; somewhere so that the CPU cannot make any extrapolations on what to fetch next 
    ; and anything being executed can finish executing. 
    jmp CODE_SEGMENT:init_pm 

    [bits 32] 
    ; Initialize segment registers. In 32 bit mode, they all point to an entry in 
    ; the GDT. 
    init_pm: 
     mov ax, DATA_SEGMENT 
     mov ds, ax 
     mov ss, ax 
     mov es, ax 
     mov fs, ax 
     mov gs, ax 

     ; Define the stack somewhere we're sure has free memory. 
     mov ebp, 0x90000 
     mov esp, ebp 

     call BeginProtectedMode 

load_kernel

[bits 16] 
KERNEL_OFFSET equ 0x1000 

; Will load the kernel into memory. 
; dl will contain the boot drive. 
LoadKernel: 
    push dx     ; Save the boot drive info 
    mov dx, LOAD_KERNEL_MSG 
    call PrintString16 
    pop dx     ; Get it back. DL contains boot drive. 

    mov bx, KERNEL_OFFSET ; Where we want kernel to be loaded to. 
    mov dh, 10    ; How many sectors to load 
    ; dl is also a parameter but we already have it. 
    call LoadFromDisk 

    ret 

%include "disk_load.s" 

LOAD_KERNEL_MSG db "Loading kernel...", 0 

ядро ​​

// Simple kernel. 
#include "screen.h" 

void main() { 
    print("It worked!"); 
    // char* video = (char*) 0xb800; 
    // video[0] = 'S'; 
} 

Makefile

INCLUDE = include/ 
# List is expanded when used not when declared. 
OBJECTS = $(wildcard temp/*.o) 

# -------------------- Build the os_image 
os_image.bin : temp/boot_sect.bin temp/kernel.bin 
    cat temp/boot_sect.bin temp/kernel.bin > os_image.bin 

# -------------------- Build the boot sector image 
temp/boot_sect.bin : boot/boot_sect.s 
    nasm boot/boot_sect.s -i boot/ -f bin -o temp/boot_sect.bin 

# -------------------- Build kernel image 
temp/kernel.bin : kernel.o kernel_entry.o 
    clang -ffreestanding -m32 kernel_entry.o $(OBJECTS) kernel.o -o temp/kernel.bin 

# -------------------- Build object files 
kernel.o : kernel/kernel.c temp/screen.o 
    clang -ffreestanding -m32 -c -I $(INCLUDE) kernel/kernel.c -o kernel.o 

kernel_entry.o : kernel/kernel_entry.s 
    nasm -f macho -o kernel_entry.o kernel/kernel_entry.s 

# -------------------- Build driver objects 
temp/screen.o : include/screen.h drivers/screen.c temp/low_level.o 
    clang -ffreestanding -m32 -c -I $(INCLUDE) drivers/screen.c -o temp/screen.o 

temp/low_level.o : include/low_level.h kernel/low_level.c 
    clang -ffreestanding -m32 -c -I $(INCLUDE) kernel/low_level.c -o temp/low_level.o 

clean : 
    rm *.o 
    rm ./temp/*.o 
    rm ./temp/*.bin 
    rm *.bin 

отношения Bochs консоль дамп

00014040953i[BIOS ] Booting from 0000:7c00 
00014479618i[FDD ] partial read() on floppy image returns 172/512 
00014561257i[MEM0 ] allocate_block: block=0x10 used 0x3 of 0x20 
00014561312e[CPU0 ] load_seg_reg(ES, 0xfffc): invalid segment 
00014561312e[CPU0 ] interrupt(): gate descriptor is not valid sys seg (vector=0x0d) 
00014561312e[CPU0 ] interrupt(): gate descriptor is not valid sys seg (vector=0x08) 
00014561312i[CPU0 ] CPU is in protected mode (active) 
00014561312i[CPU0 ] CS.mode = 32 bit 
00014561312i[CPU0 ] SS.mode = 32 bit 
00014561312i[CPU0 ] EFER = 0x00000000 
00014561312i[CPU0 ] | EAX=0008fffc EBX=00001000 ECX=00090003 EDX=ffff0136 
00014561312i[CPU0 ] | ESP=0008fff8 EBP=00090003 ESI=000e0000 EDI=00007d2d 
00014561312i[CPU0 ] | IOPL=0 id vip vif ac vm RF nt of df if tf SF zf AF pf CF 
00014561312i[CPU0 ] | SEG sltr(index|ti|rpl)  base limit G D 
00014561312i[CPU0 ] | CS:0008(0001| 0| 0) 00000000 ffffffff 1 1 
00014561312i[CPU0 ] | DS:0010(0002| 0| 0) 00000000 ffffffff 1 1 
00014561312i[CPU0 ] | SS:0010(0002| 0| 0) 00000000 ffffffff 1 1 
00014561312i[CPU0 ] | ES:0010(0002| 0| 0) 00000000 ffffffff 1 1 
00014561312i[CPU0 ] | FS:0010(0002| 0| 0) 00000000 ffffffff 1 1 
00014561312i[CPU0 ] | GS:0010(0002| 0| 0) 00000000 ffffffff 1 1 
00014561312i[CPU0 ] | EIP=0000107c (0000107c) 
00014561312i[CPU0 ] | CR0=0x60000011 CR2=0x00000000 
00014561312i[CPU0 ] | CR3=0x00000000 CR4=0x00000000 
(0).[14561312] [0x000000000000107c] 0008:000000000000107c (unk. ctxt): pop es     ; 07 
00014561312e[CPU0 ] exception(): 3rd (13) exception with no resolution, shutdown status is 00h, resetting 

ответ

0

Проблема была из Makefile и как я связывание и создания TEMP/kernel.bin двоичного.

Правило должно быть:

clang -ffreestanding -m32 kernel_entry.o kernel.o $(OBJECTS) -o temp/kernel_temp.o 
gobjcopy -O binary temp/kernel_temp.o temp/kernel.bin 

вместо этого. Мне нужно создать временный файл объекта с kernel_entry.o и kernel.o, а затем создать двоичный файл из временного файла объекта. Если вы используете OSX, вам, вероятно, придется что-то сделать, так как у нас нет доступа ко всем параметрам lux linux ld.

Смежные вопросы