【问题标题】:Reboot loop on trying to load kernel尝试加载内核时重启循环
【发布时间】:2019-02-20 00:13:02
【问题描述】:

当我尝试在 qemu 上启动时,我得到一个无休止的重启循环,我能够缩小范围

call 0x1000

这是我第一次深入研究 osdev,如果有任何其他我做错的事情,请通知我:) 提前谢谢!

[org 0x7c00]
[bits 16]
bootdrive db 0x00
xor ax,ax
mov ds, ax
mov ss, ax
mov sp, 0x9c00
mov bp, sp
mov [bootdrive], dl
mov bx, 0x1000
mov dh, 0x01
mov dl, bootdrive

loadkernel:
pusha

push dx

mov ah, 0x02
mov al, dh
mov ch, 0x00
mov dh, 0x00
mov cl, 0x02

int 0x13

pop dx

popa

setgdt:
cli
lgdt[gdtr]

call openA20

call EnablePmode

openA20:

push ax
mov ax, 0x2401
int 0x15
pop ax

ret

EnablePmode:
    mov eax, cr0
    or al, 1
    mov cr0, eax

    jmp (CODE_DESC - NULL_DESC) : Pmode
NULL_DESC:
    dd 0
    dd 0
CODE_DESC:
    dw 0xffff
    dw 0
    db 0
    db 10011010b
    db 11001111b
    db 0
DATA_DESC:
    dw 0xffff
    dw 0
    db 0
    db 10010010b
    db 11001111b
    db 0
gdtr:
    Limit dw gdtr - NULL_DESC - 1
    Base dd NULL_DESC
[bits 32]
    Pmode:
    mov ax, DATA_DESC - NULL_DESC
    mov ds, ax
    mov ss, ax
    mov es, ax
    mov fs, ax
    mov gs, ax


mov ebp, 0x90000
    mov esp, ebp

    call 0x1000

    jmp $

times 510-($-$$) db 0

dw 0xaa55

【问题讨论】:

  • 首先将数据放在代码之后和引导签名之前,否则数据将作为代码执行。
  • Int 13h/ah=2 需要将 ES 段寄存器设置为您打算在内存中读取扇区的段。 ES:BX 指向缓冲区。
  • bootdrive db 0x00 是要执行的第一条指令...
  • mov dl, bootdrive 看起来不对。你的意思可能是mov dl, [bootdrive]

标签: assembly x86 osdev


【解决方案1】:

这段代码有很多问题。

首先,确保CPU不执行0x00。

在第 3 行,您有 bootdrive db 0。 它应该是这样的:

[BITS 16]
[ORG 0x7C00]
jmp main
bootdev db 0
main:

第二个是你试图将一个词(bootdev 的指针)分配给 DL。这是不正确的。它应该如下所示:

mov dl,[bootdev]

您正在尝试读取 Head:0 Cylinder/Track:0 和 Sector 2。您认为它将加载到 BX 地址 0x1000。但它会在 [ES:BX] 加载。如果你想跳转 0x1000, 然后确保 ES 为 0。

xor ax,ax ;AX is 0 now.
mov es,ax ;Thats how you reset ES.

您应该在加载 GDT 之前启用 A20。

您的新代码应如下所示:

[org 0x7c00]
[bits 16]
jmp main
bootdrive db 0x00
main:
xor ax,ax
mov ds, ax
mov ss, ax
mov sp, 0x9c00
mov bp, sp
mov [bootdrive], dl
mov bx, 0x1000
mov dh, 0x01
mov dl, [bootdrive]

loadkernel:
pusha

push dx
xor ax,ax
mov es,ax
mov ah, 0x02
mov al, dh
mov ch, 0x00
mov dh, 0x00
mov cl, 0x02

int 0x13

pop dx

popa

setgdt:
cli
call openA20
lgdt[gdtr]
call EnablePmode
openA20:

push ax
mov ax, 0x2401
int 0x15
pop ax

ret

EnablePmode:
    mov eax, cr0
    or al, 1
    mov cr0, eax

    jmp (CODE_DESC - NULL_DESC) : Pmode
NULL_DESC:
    dd 0
    dd 0
CODE_DESC:
    dw 0xffff
    dw 0
    db 0
    db 10011010b
    db 11001111b
    db 0
DATA_DESC:
    dw 0xffff
    dw 0
    db 0
    db 10010010b
    db 11001111b
    db 0
gdtr:
    Limit dw gdtr - NULL_DESC - 1
    Base dd NULL_DESC
[bits 32]
    Pmode:
    mov ax, DATA_DESC - NULL_DESC
    mov ds, ax
    mov ss, ax
    mov es, ax
    mov fs, ax
    mov gs, ax


mov ebp, 0x90000
    mov esp, ebp


    call 0x1000

    jmp $

times 510-($-$$) db 0

dw 0xaa55

还有内核:

BITS 32
org 0x1000
Start:
mov eax,0xB8000
mov byte [eax],78
mov byte [eax+1],71
jmp $

它将在左上角打印红色背景灰色“N”。

编码愉快!

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-02-24
    • 1970-01-01
    • 1970-01-01
    • 2014-10-13
    • 2023-03-20
    • 2018-05-22
    • 1970-01-01
    相关资源
    最近更新 更多