2013-07-31 33 views
-1

装好吧,我已经撕裂了剩余的头发我有这个问题...内核未正确处地址

基本上,我正在试图建立一个非常简单的爱好OS。操作系统将运行在X86平台上,不使用FAT12软盘。在我的机器上测试它之前,我创建了一个磁盘映像用Bochs 2.6.2进行测试。与往常一样,我将引导程序放到磁盘映像的引导扇区上,然后将内核映像(KERNEL.SYS)添加为常规FAT12文件。

引导加载程序的目的是要找到KERNEL.SYS,将其加载到地址1000h:0000,并跳转到它。

然而,当我测试与Bochs的磁盘映像,我得到这些结果(从跳跃开始07C0:0000):

Results

从我的知识,我知道的Bochs要么不断复位(三重故障?)还是回到0000:0000(A20未启用)。内核启动时有一个无限循环(JMP $)(出于测试原因),所以我知道它没有执行。我也知道1000:000不超过1 MB,所以我不确定。

这真是困扰我的部分:当我从Bochs(32 MB)获取内存转储时,我看到KERNEL.SYS在0980:0000或0000:9800加载。我知道一个事实,那就是我从来没有装过任何东西,所以发生了什么?

Bootloader代码:

[BITS 16] 
[ORG 0x00] 

JMP btldr_init 
NOP 

OEMName   DB 'MAGMAPRE' 
BytesPerSector  DW 0x0200 
SectorsPerCluster DB 0x01 
ReservedSectors  DW 0x0001 
NumberOfFATS  DB 0x02 
MaxRDirEntries  DW 0x00E0 
TotalSectors  DW 0x0B40 
MediaDescriptor  DB 0xF0 
SectorsPerFAT  DW 0x0009 
SectorsPerTrack  DW 0x0012 
NumberOfHeads  DW 0x0002 
HiddenSectors  DD 0x00000000 
TotalSectorsL  DD 0x00000000 

DriveNumber  DW 0x0000 
Reserved  DB 0x00 
VolumeID  DD 0xF00DCAFE 
VolumeName  DB 'MAGMA DISK ' 
FileSysID  DB 'FAT12 ' 

btldr_init: 

    MOV AX, 0x07C0 
    MOV DS, AX 
    MOV  ES, AX 
    MOV SS, AX 

    MOV SP, 0x7C00 

    MOV DI, 0x03 

read_rdir: 

    MOV [driveNo], DL 

    MOV AX, 0x13 

    CALL dos_to_bios 


    MOV AX, 0x020E 
    MOV BX, buffer 

    CALL reset_dsksys 

    STC 
    INT 0x13 

    JNC search_rdir 

    DEC DI 
    JZ fatal_error 

    JMP read_rdir 

search_rdir: 

    MOV DI, buffer 
    MOV SI, knlName 
    MOV DX, [MaxRDirEntries] 

.compare: 

    PUSH DI 
    PUSH SI 

    CLD 

    MOV CX, 0x0B 

    REP CMPSB 

    JE load_disk_fath 

    POP SI 
    POP DI 

.next_entry: 

    DEC DX 
    JZ fatal_error 

    ADD DI, 0x20 
    JMP .compare 

load_disk_fath: 

    POP SI 
    POP DI 

    MOV AX, word [DS:DI+0x1A] 
    MOV [cluster], AX 
    MOV AX, word [DS:DI+0x1C] 
    MOV [knlSize], AX 

    MOV DI, 0x03 

load_disk_fat: 

    MOV AX, [ReservedSectors] 
    CALL dos_to_bios 

    MOV AX, 0x0209 

    MOV BX, buffer 

    STC 
    INT 0x13 

    JNC load_file_clusterh 

    DEC DI 
    JZ fatal_error 

    JMP load_disk_fat 

load_file_clusterh: 

    MOV DI, 0x03 

    MOV AX, 0x1000 
    MOV ES, AX 

load_file_cluster: 

    MOV AX, [cluster] 
    ADD AX, 0x21 

    CALL dos_to_bios 

    MOV AX, 0x0201 

    MOV BX, [bufPos] 
    CMP BX, [knlSize] 
    JAE get_info 

    STC 
    INT 0x13 

    JC .try_again 

    MOV BX, [bufPos] 
    ADD BX, 0x200 
    MOV [bufPos], BX 
    JMP get_next_cluster 

.try_again: 

    DEC DI 
    JZ fatal_error 

    JMP load_file_cluster 

get_next_cluster: 

    MOV AX, [cluster] 
    MOV BX, [cluster] 

    SHR BX, 0x01 

    ADD BX, AX 

    MOV DX, [DS:BX+buffer] 

    TEST BX, 0x01 

    JNZ .even 

.odd: 

    SHR DX, 0x04 
    JMP .check 

.even: 

    AND DX, 0x0FFF 

.check: 

    CMP DX, 0xFF0 
    JE get_info 

    MOV [cluster], DX 

    ;JMP load_file_cluster 

get_info: 

    MOV AX, 0x0BE0 
    MOV ES, AX 
    MOV DI, 0x02 
    XOR SI, SI 

.low_mem: 

    XOR AX, AX 
    INT 0x12 

    JC .low_mem_err 

    TEST AX, AX 
    JZ .low_mem_err 

.low_mem_success: 

    MOV [ES:DI], AX 
    JMP .upper_memE801 

.low_mem_err: 

    XOR DI, DI 
    OR SI, 0x0001 
    MOV [ES:DI], SI 

.upper_memE801: 

    XOR  CX, CX 
    XOR  DX, DX 
    MOV  AX, 0xE801 
    INT  0x15   
    JC SHORT .upper_mem_err 
    CMP  AH, 0x86  
    JE SHORT .upper_mem_err 
    CMP  AH, 0x80  
    JE SHORT .upper_mem_err 
    JCXZ .useax  

    MOV  AX, CX 
    MOV  BX, DX 
    JMP .useax 

.upper_mem_err: 

    JMP .upper_mem88 

.useax: 

    MOV DI, 0x04 
    MOV [ES:DI], AX 
    ADD DI, 0x02 
    MOV [ES:DI], BX 
    JMP goto_kernel 

.upper_mem88: 

    MOV AH, 0x88 
    INT  0x15   
    JC SHORT .upper_mem_err88 
    TEST AX, AX  
    JE SHORT .upper_mem_err88 
    CMP  AH, 0x86   
    JE SHORT .upper_mem_err88 
    CMP  AH, 0x80   
    JE SHORT .upper_mem_err88 

.success: 

    MOV DI, 0x08 
    MOV [ES:DI], AX 
    JMP goto_kernel 

.upper_mem_err88: 

    OR SI, 0x0002 

goto_kernel: 


    JMP 1000h:0000 

reset_dsksys: 

    PUSHA 

    XOR AX, AX 
    MOV DL, [driveNo] 

    INT 0x13 

    JC fatal_error 

    POPA 
    RET 

fatal_error: 

.repeat: 

    MOV AL, [DS:SI] 
    OR AL, AL 
    JZ .end 

    MOV AH, 0x0E 
    INT 0x10 

    INC SI 
    JMP .repeat 

.end: 

    CLI 
    HLT 

dos_to_bios: 

    PUSH BX 
    PUSH AX 

    MOV  BX, AX   ; SAVE LOGICAL SECTOR 

    MOV  DX, 0   ; FIRST THE SECTOR 
    DIV WORD [SectorsPerTrack] 
    ADD  DL, 01H   ; PHYSICAL SECTORS START AT 1 
    MOV  CL, DL   ; SECTORS BELONG IN CL FOR INT 13H 
    MOV AX, BX 

    MOV  DX, 0   ; NOW CALCULATE THE HEAD 
    DIV  WORD [SectorsPerTrack] 
    MOV  DX, 0 
    DIV  WORD [NumberOfHeads] 
    MOV  DH, DL   ; HEAD/SIDE 
    MOV  CH, AL   ; TRACK 

    POP AX 
    POP  BX 

    MOV  DL, BYTE [driveNo]  ; SET CORRECT DEVICE 


    RET 

knlName  DB 'KERNEL SYS' 

knlSize  DW 0x0000 

err  DB 'Could not load Magma.', 0x00 

driveNo  DB 0x00 

cluster  DW 0x0000 
cOffset  DW 0x0000 
bufPos  DW 0x0000 

TIMES 510 - ($ - $$) DB 0x00 

DB 0x55 
DB 0xAA 

buffer: 
+0

我会使用GRUB bootloader,并专注于正确的内核开发。不要花太多时间在引导加载(这不是练习的有趣部分)。另请参阅http://wiki.osdev.org/Main_Page –

+0

@BasileStarynkevitch - 是的,我知道bootloader是操作系统开发非常平淡的一部分。但是,我更喜欢使用自己的代码而不是其他预制对象;)。 – s0d4pop

+0

干得好!在明确设置ds之前执行mov [driveNo],dl'是个错误,恕我直言。我不认为这是你的问题。在跳转之前,尝试查找ds = 1000h的0xEBFE和偏移量0。显然,它不在那里。从那里倒退。 –

回答

0

好了,一切似乎是好了,这个问题也许是别的地方。 (顺便说一句,在int 13h之前不需要STC,但这不能成为所述问题的原因)。

因此,我会建议尝试使用Bochs调试器,并在源代码中的关键位置插入int3断点 - 例如在内核读取操作之前,在远程跳转之前(您可以检查加载的内容$ 1000:0000

另外要注意的,也不是很重要的,就是SP值7C00h处是有点不为SP平常值,但无论如何,它是不是很明显的问题

而且,内核代码必须是。再次检查一次

0

有一件事似乎与你的代码有关,你将Stack段设置为07C0,然后堆栈指针指向7C00,所以堆栈位于07C0:7C00或0000:F800,这不是导致AFAIK失败的原因。你应该考虑的事情是,bootrecord可以加载到0000:7C00或07C0:0000取决于BIOS,它是一个好主意,规范化代码段跳远只是为了安全,还记得它只要它始终如一,只要在07C0:0000或0000:7C00发起它就没有关系。

如前所述,在INT 13h之前不需要STC,您可以省略这些以节省空间,更好的方法是调用重置磁盘的子例程,将LBA转换为CHS并读取扇区全部在一段代码中,而不是在整个代码的其余部分分散读取代码。同样,当重置磁盘时,如果驱动器没有准备好,它将设置进位标志,并且保持调用INT 13h AX = 0直到进位标志清除是完全安全的。

如果你看看你声称加载内核的地址,将其转换为绝对地址,然后返回到段偏移量,并将其加载到07C00h的段中,即将内核加载到07C0:1C00,如果问题是细分。