2015-02-07 5 views
0

Я написал очень простое ядро ​​C и загрузчик. Я загрузка ядра в QEMU, как это:QEMU сбой при выполнении метода

qemu-system-i386 kernel.image 

Когда я загрузить ядро ​​и перейти от реального режима в защищенном режиме (этот шаг успех завершен) и main способом начать выполнение другого метода, как этот void foo(int a, int b, int c, int d, int e) {return;}. Но его выполнение приводит к сбою QEMU. Однако, если я переписал метод foo для void foo(int a, int b, int c, int d) {return;} - все будет в порядке. Вот информация об ошибке: (QEMU) QEMU: со смертельным исходом: Попытка выполнить код вне ОЗУ или ПЗУ на 0xf4000010

EAX=ffffffff EBX=00001000 ECX=00000000 EDX=00000000 
ESI=00000000 EDI=00000000 EBP=ae00008f ESP=00008fcd 
EIP=f4000010 EFL=00000006 [-----P-] CPL=0 II=0 A20=1 SMM=0 HLT=0 
ES =0010 00000000 ffffffff 00cf9300 DPL=0 DS [-WA] 
CS =0008 00000000 ffffffff 00cf9a00 DPL=0 CS32 [-R-] 
SS =0010 00000000 ffffffff 00cf9300 DPL=0 DS [-WA] 
DS =0010 00000000 ffffffff 00cf9300 DPL=0 DS [-WA] 
FS =0010 00000000 ffffffff 00cf9300 DPL=0 DS [-WA] 
GS =0010 00000000 ffffffff 00cf9300 DPL=0 DS [-WA] 
LDT=0000 00000000 0000ffff 00008200 DPL=0 LDT 
TR =0000 00000000 0000ffff 00008b00 DPL=0 TSS32-busy 
GDT=  00007c75 00000017 
IDT=  00000000 000003ff 
CR0=00000011 CR2=00000000 CR3=00000000 CR4=00000000 
DR0=00000000 DR1=00000000 DR2=00000000 DR3=00000000 
DR6=ffff0ff0 DR7=00000400 
CCS=00000000 CCD=00008fc5 CCO=INCL  
EFER=0000000000000000 
FCW=037f FSW=0000 [ST=0] FTW=00 MXCSR=00001f80 
FPR0=0000000000000000 0000 FPR1=0000000000000000 0000 
FPR2=0000000000000000 0000 FPR3=0000000000000000 0000 
FPR4=0000000000000000 0000 FPR5=0000000000000000 0000 
FPR6=0000000000000000 0000 FPR7=0000000000000000 0000 
XMM00=00000000000000000000000000000000  XMM01=00000000000000000000000000000000 
XMM02=00000000000000000000000000000000 XMM03=00000000000000000000000000000000 
XMM04=00000000000000000000000000000000 XMM05=00000000000000000000000000000000 
XMM06=00000000000000000000000000000000 XMM07=00000000000000000000000000000000 

Мои bootloader.S

KERNEL_OFFSET equ 0x1000 

[org 0x7c00] 
[bits 16] 
    mov bp, 0x8000 
    mov sp, bp  
    mov bx, bootstring 
    call print   

    mov [BOOT_DRIVE], dl 
    mov dh, 3h   
    mov bx, KERNEL_OFFSET 
    call load_kernel 
    call enable_A20 
    call init_protected 
loop: 
    jmp loop 

bootstring: db "Loading...", 0 
BOOT_DRIVE: db 0 

print: 
    mov ah, 0xE 
    mov al, [bx] 
    cmp al, 0  
    jz print_done 
    int 0x10  
    inc bx  
    jmp print  
print_done: 
    ret 

load_kernel: 
    push dx   
    mov ah, 0x02 
    mov al, dh  
    mov ch, 0  
    mov cl, 2  
    mov dh, 0  
    int 0x13  
    jc load_error 
    pop dx   
    cmp al, dh  

    jne load_error 
    ret 

load_error: 
    mov bx, load_err_msg 
    call print 
    jmp $ 

enable_A20: 
    cli 

    call a20wait 
    mov al, 0xAD 
    out 0x64, al 

    call a20wait 
    mov al, 0xD0 
    out 0x64, al 

    call a20wait2 
    in al, 0x60 
    push eax 

    call a20wait 
    mov al, 0xD1 
    out 0x64, al 

    call a20wait 
    pop eax 
    or al, 2 
    out 0x60, al 

    call a20wait 
    mov al, 0xAE 
    out 0x64, al 

    call a20wait 
    sti 
    ret 

a20wait: 
    in al, 0x64 
    test al, 2 
    jnz a20wait 
    ret 

a20wait2: 
    in al, 0x64 
    test al, 1 
    jz a20wait2 
    ret 

load_err_msg: db "Cannot load from disk", 0 

gdt:     
gdt_null: 
    dd 0 
    dd 0 
gdt_cs: 
    dw 0xffff 
    dw 0  
    db 0  
    db 10011010b 

    db 11001111b 
    db 0   
gdt_ds: 
    dw 0xffff 
    dw 0   
    db 0   
    db 10010010b 

    db 11001111b 
    db 0   
gdt_end:   

gdt_desc: 
    dw gdt_end - gdt - 1 
    dd gdt 

CODE_SEG equ gdt_cs - gdt 
DATA_SEG equ gdt_ds - gdt 

[bits 16] 
init_protected: 
    cli 
    xor ax, ax 
    mov ds, ax 
    mov es, ax 
    mov ax, 0x9000  
    mov ss, ax 
    mov sp, 0xFFFF 
    lgdt [gdt_desc] 
    mov eax, cr0 
    or eax, 0x1 
    mov cr0, eax 
    jmp CODE_SEG:start_protected 

[bits 32] 

start_protected: 
    mov ax, DATA_SEG 
    mov ds, ax 
    mov es, ax 
    mov fs, ax 
    mov gs, ax 
    mov ss, ax 
    mov esp, 0x9000 
    call KERNEL_OFFSET 

times 510 -($ - $$) db 0 
dw 0xAA55 

Где я ошибаюсь?

+0

Вы действительно ожидаете от нас отладить ваше ядро, не предоставив нам свое ядро? Очевидно, что вы нарушаете защиту * как-то *, но как действительно невозможно сказать. –

+0

Действительно? Ты серьезно? Дайте нам код ядру. – SevenBits

+0

@ MarcusMüller Извините, я редактирую сообщение;) – dvigal

ответ

1

Симптомы указывают на то, что ваша стекная память не настроена правильно - похоже, что все идет не так, когда есть достаточное количество аргументов для функции, которые некоторые из них должны выполнять в стеке, а не все, находящиеся в регистрах. Сообщение от QEMU сообщает вам, что ваш гость попытался выполнить с физического адреса без ОЗУ. Вы должны уметь отлаживать то, что точно пошло не так, используя параметры ведения журнала отладки (-d in_asm, exec, cpu, int -D qemu.log), чтобы узнать, что действительно сделал ЦП, чтобы добраться до точки, где она пыталась выполнить из неверный адрес.

Обратите внимание, что хотя сообщение об ошибке QEMU немного напоминает «QEMU crashed», оно всегда указывает на ошибку гостевой ОС.

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