2013-07-31 36 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,如果問題是細分。