2012-06-27 27 views
2

Here's我的引導加載程序代碼和here's一個文檔顯示寄存器的圖片(萬一在我做錯了什麼是重要的),什麼在位置0x10000(我告訴引導加載程序加載內核),內核的源程序集以及Qemu運行時的屏幕輸出的內存中。引導加載程序總是混淆了Int 13h調用的前兩個字節來加載內核

kernelStub.bin在最開始有EB 1B(右跳命令)。 hda.img在第二部門開始時的55 AA之後擁有EB 1B。進位標誌在我的load_mem子程序中清楚表明它相信負載很好。所有的字節在內存中是正確的,除了前兩個總是63 61.

爲什麼load_mem例程總是將扇區2的前兩個字節加載到地址0x10000錯誤,然後讓剩下的權利呢?

的Bootloader代碼:

更新:改變jmp SYSADDR:0000jmp 0x1000:0x0000每馬修·斯萊特里的修正。

;Very minimal boot loader 
BITS 16    ;Tell assembler to use 16-bit mode 
jmp start    ;Jump over defines 
SYSADDR dw 0x1000  ;Load system at 0x10000 
DRIVENUM db 0x80  ;Variable for drive number 
HEADNUM db 0 
CYLNUM db 0   ;Low bits of cylinder number 
SECTNUM db 2   ;Bits 6 and 7 high bits of cylinder number (0), 
         ;Bits 0-5 starting sector number (2) 
NUMKERNELSECTS db 0x01 ;Will Probably Change! Number of sectors 
         ;to read from disk 
load_msg db 'Loading OS', 0 
msg_2  db 'carry flag not clear', 0 
load_worked db 'Load worked', 0 

start: 
    mov ax, 0x07C0  ;Set data segment to where BIOS loaded boot loader 
    mov ds, ax 
    mov si, load_msg ;Simple text string to indicate loading 
    call show_message 
    call load_mem  ;Subroutine to load bytes from disk to location 
         ;pointed to by es 
    jmp 0x1000:0x0000 

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 
;Subroutines 

;;;Show Message;;; 
show_message: 
    mov ah, 0x0E  ;int 0x10 print character to screen function 
.repeat: 
    lodsb    ;Get char pointed to by si, puts in al 
    cmp al, 0   ;see if char is 0 (null) 
    je .done   ;null signifies done 
    int 0x10   ;If not null, print to screen 
    jmp .repeat  ;Get next char 

.done: 
    ret 

;;;Load Memory;;; 
load_mem: 
    xor ah, ah   ;ah=0, reset drive 
    int 0x13   ;Call drive reset 

    mov ax, [SYSADDR] 
    mov es, ax   ;Destination- es:bx 
    mov bx, 0 
    mov dl, [DRIVENUM] 
    mov dh, [HEADNUM] 
    mov al, [NUMKERNELSECTS] 
    mov ch, [CYLNUM] 
    mov cl, [SECTNUM] 
    mov ah, 0x02  ;ah=2, read drive 
    int 0x13   ;Call read interrupt 
    jnc exit   ;If carry flag is clear, exit 

exit: 
    ret 

times 510 - ($-$$) db 0;Pad sector with 0 
dw 0xAA55    ;Boot signature 
+0

請在此填寫您的代碼,以便將來不會改變或丟失。 –

回答

4
SYSADDR dw 0x1000 ;Load system at 0x10000 
... 
jmp SYSADDR:0000 

不會做你希望它是什麼。 SYSADDR是你想要的值的位置(0x0002這裏),而不是值本身。我認爲執行0x0002:0000(它甚至不是真正的代碼;它是中斷向量表的一部分)的任何內容都會導致數據被潦草地覆蓋。

(順便說一下,至少有一個以上的問題,以及:在你的第二個鏈接的文檔內核存根代碼未重置ds


編輯:

我見你已經有了這方面的工作了,但爲了完整,我有這兩個字節神祕值 充分的解釋,其結果是jmp SYSADDR:0000錯誤的 :

0002:0000,即地址0x20,是INT 08h的載體。

傳統的入口點地址INT 08h處理程序f000:fea5(BIOS的 傾向於維護使用 入口點直接的傳統,與代碼兼容性)。所以這個地址的字節幾乎肯定會是 是a5 fe 00 f0 ...

如果執行第一那些字節,a5的,因爲代碼,它是一個movsw 指令,該副本的兩個字節從ds:sies:di

  • ds仍然是你的引導裝載程序的數據段
  • si點的msg_2開始(在您show_message日常 離開它打印load_msg後)
  • es仍然0x1000
  • di大概包含0

因此,在jmp 0x0002:0000之後發生的第一件事是將從msg_2開始的 ca複製到加載的扇區的前兩個字節 。

+0

我也試過jmp 0x1000:0x0000,它仍然不起作用,因爲EB 1B的正確跳轉不在地址0x10000,即使我在那裏跳轉。感謝ds的更正。 – mring

+0

非常整齊。現在我知道那些神祕價值從何而來。謝謝! – mring

0

我發現關於我的內核here第一跳的問題的關鍵細節。我不知道這是多麼必要(至少有一些BIOS)跟着jmpnop

有一次,我把nop s和設置我的ds註冊,它終於奏效。