2013-10-25 125 views
0

我試圖開發操作系統,並認爲我有些東西有點作用。然而,當我組裝成.iso文件是這樣的:OS加載到VB時返回錯誤

nasm -f bin -o kernel.bin kernel.asm 
nasm -f bin -o boot.bin boot.asm 
dd if=boot.bin of=os.iso bs=512 count=1 
dd if=kernel.bin of=os.iso bs=512 count=1 

,並嘗試運行它作爲一個在虛擬盒,我收到以下錯誤信息:

Failed to open the CD/DVD image /home/logan/Desktop/OS/test.iso. 
The medium '/home/logan/Desktop/OS/test.iso' can't be used as the requested device type. 

基本上,我我想知道發生了什麼,如果它與代碼有關,或者它是格式錯誤,以及我如何修復它。

這是兩個文件我用:

kernel.bin:

mov ax, 0x07C0 ; set up segments 
    mov ds, ax 
    mov es, ax 

    mov si, welcome 
    call print_string 

mainloop: 
    mov si, prompt 
    call print_string 

    mov di, buffer 
    call get_string 

    mov si, buffer 
    cmp byte [si], 0 ; blank line? 
    je mainloop  ; yes, ignore it 

    mov si, buffer 
    mov di, cmd_hi ; "hi" command 
    call strcmp 
    jc .helloworld 

    mov si, buffer 
    mov di, cmd_help ; "help" command 
    call strcmp 
    jc .help 

    mov si,badcommand 
    call print_string 
    jmp mainloop 

.helloworld: 
    mov si, msg_helloworld 
    call print_string 

    jmp mainloop 

.help: 
    mov si, msg_help 
    call print_string 

    jmp mainloop 

welcome db 'Welcome to My OS!', 0x0D, 0x0A, 0 
msg_helloworld db 'Hello OSDev World!', 0x0D, 0x0A, 0 
badcommand db 'Bad command entered.', 0x0D, 0x0A, 0 
prompt db '>', 0 
cmd_hi db 'hi', 0 
cmd_help db 'help', 0 
msg_help db 'My OS: Commands: hi, help', 0x0D, 0x0A, 0 
buffer times 64 db 0 

; ================ 
; calls start here 
; ================ 

print_string: 
    lodsb  ; grab a byte from SI 

    or al, al ; logical or AL by itself 
    jz .done ; if the result is zero, get out 

    mov ah, 0x0E 
    int 0x10  ; otherwise, print out the character! 

    jmp print_string 

.done: 
    ret 

get_string: 
    xor cl, cl 

.loop: 
    mov ah, 0 
    int 0x16 ; wait for keypress 

    cmp al, 0x08 ; backspace pressed? 
    je .backspace ; yes, handle it 

    cmp al, 0x0D ; enter pressed? 
    je .done  ; yes, we're done 

    cmp cl, 0x3F ; 63 chars inputted? 
    je .loop  ; yes, only let in backspace and enter 

    mov ah, 0x0E 
    int 0x10  ; print out character 

    stosb ; put character in buffer 
    inc cl 
    jmp .loop 

.backspace: 
    cmp cl, 0 ; beginning of string? 
    je .loop ; yes, ignore the key 

    dec di 
    mov byte [di], 0 ; delete character 
    dec cl  ; decrement counter as well 

    mov ah, 0x0E 
    mov al, 0x08 
    int 10h  ; backspace on the screen 

    mov al, ' ' 
    int 10h  ; blank character out 

    mov al, 0x08 
    int 10h  ; backspace again 

    jmp .loop ; go to the main loop 

.done: 
    mov al, 0 ; null terminator 
    stosb 

    mov ah, 0x0E 
    mov al, 0x0D 
    int 0x10 
    mov al, 0x0A 
    int 0x10  ; newline 

    ret 

strcmp: 
.loop: 
    mov al, [si] ; grab a byte from SI 
    mov bl, [di] ; grab a byte from DI 
    cmp al, bl  ; are they equal? 
    jne .notequal ; nope, we're done. 

    cmp al, 0 ; are both bytes (they were equal before) null? 
    je .done ; yes, we're done. 

    inc di  ; increment DI 
    inc si  ; increment SI 
    jmp .loop ; loop! 

.notequal: 
    clc ; not equal, clear the carry flag 
    ret 

.done:  
    stc ; equal, set the carry flag 
    ret 

; times 510-($-$$) db 0 
    dw 0AA55h ; some BIOSes require this signature 

BOOT.BIN:

; ================================================================== 
; The DIOS Boot-Loader 
; Copyright (C) 2013 ELEMENTAL Developers -- see doc/LICENSE.TXT 
; 
; Based on a free boot loader by MikeOS Developers. It scans the FAT12 
; floppy for KERNEL.BIN (the ELEMENTAL kernel), loads it and executes it. 
; This must grow no larger than 512 bytes (one sector), with the final 
; two bytes being the boot signature (AA55h). Note that in FAT12, 
; a cluster is the same as a sector: 512 bytes. 
; ================================================================== 


    BITS 16 

    jmp short bootloader_start ; Jump past disk description section 
    nop    ; Pad out before disk description 


; ------------------------------------------------------------------ 
; Disk description table, to make it a valid floppy 
; Note: some of these values are hard-coded in the source! 
; Values are those used by IBM for 1.44 MB, 3.5" diskette 

OEMLabel  db "ELEMENTAL" ; Disk label 
BytesPerSector  dw 512  ; Bytes per sector 
SectorsPerCluster db 1  ; Sectors per cluster 
ReservedForBoot  dw 1  ; Reserved sectors for boot record 
NumberOfFats  db 2  ; Number of copies of the FAT 
RootDirEntries  dw 224  ; Number of entries in root dir 
        ; (224 * 32 = 7168 = 14 sectors to read) 
LogicalSectors  dw 2880  ; Number of logical sectors 
MediumByte  db 0F0h  ; Medium descriptor byte 
SectorsPerFat  dw 9  ; Sectors per FAT 
SectorsPerTrack  dw 18  ; Sectors per track (36/cylinder) 
Sides   dw 2  ; Number of sides/heads 
HiddenSectors  dd 0  ; Number of hidden sectors 
LargeSectors  dd 0  ; Number of LBA sectors 
DriveNo   dw 0  ; Drive No: 0 
Signature  db 41  ; Drive signature: 41 for floppy 
VolumeID  dd 00000000h ; Volume ID: any number 
VolumeLabel  db "HELIOS  "; Volume Label: any 11 chars 
FileSystem  db "FAT12 " ; File system type: don't change! 


; ------------------------------------------------------------------ 
; Main bootloader code 


bootloader_start: 
    mov ax, 07C0h   ; Set up 4K of stack space above buffer 
    add ax, 544   ; 8k buffer = 512 paragraphs + 32 paragraphs (loader) 
    cli    ; Disable interrupts while changing stack 
    mov ss, ax 
    mov sp, 4096 
    sti    ; Restore interrupts 

    mov ax, 07C0h   ; Set data segment to where we're loaded 
    mov ds, ax 

    ; NOTE: A few early BIOSes are reported to improperly set DL 

    cmp dl, 0 
    je no_change 
    mov [bootdev], dl  ; Save boot device number 
    mov ah, 8   ; Get drive parameters 
    int 13h 
    jc fatal_disk_error 
    and cx, 3Fh   ; Maximum sector number 
    mov [SectorsPerTrack], cx ; Sector numbers start at 1 
    movzx dx, dh   ; Maximum head number 
    add dx, 1   ; Head numbers start at 0 - add 1 for total 
    mov [Sides], dx 

no_change: 
    mov eax, 0   ; Needed for some older BIOSes 

; Start of root = ReservedForBoot + NumberOfFats * SectorsPerFat = logical 19 
; Number of root = RootDirEntries * 32 bytes/entry/512 bytes/sector = 14 
; Start of user data = (start of root) + (number of root) = logical 33 

floppy_ok:    ; Ready to read first block of data 
    mov ax, 19   ; Root dir starts at logical sector 19 
    call l2hts 

    mov si, buffer   ; Set ES:BX to point to our buffer (see end of code) 
    mov bx, ds 
    mov es, bx 
    mov bx, si 

    mov ah, 2   ; Params for int 13h: read floppy sectors 
    mov al, 14   ; And read 14 of them 

    pusha    ; Prepare to enter loop 


read_root_dir: 
    popa    ; In case registers are altered by int 13h 
    pusha 

    stc    ; A few BIOSes do not set properly on error 
    int 13h    ; Read sectors using BIOS 

    jnc search_dir   ; If read went OK, skip ahead 
    call reset_floppy  ; Otherwise, reset floppy controller and try again 
    jnc read_root_dir  ; Floppy reset OK? 

    jmp reboot   ; If not, fatal double error 


search_dir: 
    popa 

    mov ax, ds   ; Root dir is now in [buffer] 
    mov es, ax   ; Set DI to this info 
    mov di, buffer 

    mov cx, word [RootDirEntries] ; Search all (224) entries 
    mov ax, 0   ; Searching at offset 0 


next_root_entry: 
    xchg cx, dx   ; We use CX in the inner loop... 

    mov si, kern_filename  ; Start searching for kernel filename 
    mov cx, 11 
    rep cmpsb 
    je found_file_to_load  ; Pointer DI will be at offset 11 

    add ax, 32   ; Bump searched entries by 1 (32 bytes per entry) 

    mov di, buffer   ; Point to next entry 
    add di, ax 

    xchg dx, cx   ; Get the original CX back 
    loop next_root_entry 

    mov si, file_not_found  ; If kernel is not found, bail out 
    call print_string 
    jmp reboot 


found_file_to_load:   ; Fetch cluster and load FAT into RAM 
    mov ax, word [es:di+0Fh] ; Offset 11 + 15 = 26, contains 1st cluster 
    mov word [cluster], ax 

    mov ax, 1   ; Sector 1 = first sector of first FAT 
    call l2hts 

    mov di, buffer   ; ES:BX points to our buffer 
    mov bx, di 

    mov ah, 2   ; int 13h params: read (FAT) sectors 
    mov al, 9   ; All 9 sectors of 1st FAT 

    pusha    ; Prepare to enter loop 


read_fat: 
    popa    ; In case registers are altered by int 13h 
    pusha 

    stc 
    int 13h    ; Read sectors using the BIOS 

    jnc read_fat_ok   ; If read went OK, skip ahead 
    call reset_floppy  ; Otherwise, reset floppy controller and try again 
    jnc read_fat   ; Floppy reset OK? 


; ****************************************************************** 
fatal_disk_error: 
; ****************************************************************** 
    mov si, disk_error  ; If not, print error message and reboot 
    call print_string 
    jmp reboot   ; Fatal double error 


read_fat_ok: 
    popa 

    mov ax, 2000h   ; Segment where we'll load the kernel 
    mov es, ax 
    mov bx, 0 

    mov ah, 2   ; int 13h floppy read params 
    mov al, 1 

    push ax    ; Save in case we (or int calls) lose it 


; Now we must load the FAT from the disk. Here's how we find out where it starts: 
; FAT cluster 0 = media descriptor = 0F0h 
; FAT cluster 1 = filler cluster = 0FFh 
; Cluster start = ((cluster number) - 2) * SectorsPerCluster + (start of user) 
;    = (cluster number) + 31 


load_file_sector: 
    mov ax, word [cluster]  ; Convert sector to logical 
    add ax, 31 

    call l2hts   ; Make appropriate params for int 13h 

    mov ax, 2000h   ; Set buffer past what we've already read 
    mov es, ax 
    mov bx, word [pointer] 

    pop ax    ; Save in case we (or int calls) lose it 
    push ax 

    stc 
    int 13h 

    jnc calculate_next_cluster ; If there's no error... 

    call reset_floppy  ; Otherwise, reset floppy and retry 
    jmp load_file_sector 


    ; In the FAT, cluster values are stored in 12 bits, so we have to 
    ; do a bit of maths to work out whether we're dealing with a byte 
    ; and 4 bits of the next byte -- or the last 4 bits of one byte 
    ; and then the subsequent byte! 

calculate_next_cluster: 
    mov ax, [cluster] 
    mov dx, 0 
    mov bx, 3 
    mul bx 
    mov bx, 2 
    div bx    ; DX = [cluster] mod 2 
    mov si, buffer 
    add si, ax   ; AX = word in FAT for the 12 bit entry 
    mov ax, word [ds:si] 

    or dx, dx   ; If DX = 0 [cluster] is even; if DX = 1 then it's odd 

    jz even    ; If [cluster] is even, drop last 4 bits of word 
        ; with next cluster; if odd, drop first 4 bits 

odd: 
    shr ax, 4   ; Shift out first 4 bits (they belong to another entry) 
    jmp short next_cluster_cont 


even: 
    and ax, 0FFFh   ; Mask out final 4 bits 


next_cluster_cont: 
    mov word [cluster], ax  ; Store cluster 

    cmp ax, 0FF8h   ; FF8h = end of file marker in FAT12 
    jae end 

    add word [pointer], 512  ; Increase buffer pointer 1 sector length 
    jmp load_file_sector 


end:     ; We've got the file to load! 
    pop ax    ; Clean up the stack (AX was pushed earlier) 
    mov dl, byte [bootdev]  ; Provide kernel with boot device info 

    jmp 2000h:0000h   ; Jump to entry point of loaded kernel! 

; ------------------------------------------------------------------ 
; BOOTLOADER SUBROUTINES 

reboot: 
    mov ax, 0 
    int 16h    ; Wait for keystroke 
    mov ax, 0 
    int 19h    ; Reboot the system 


print_string:    ; Output string in SI to screen 
    pusha 

    mov ah, 0Eh   ; int 10h teletype function 

.repeat: 
    lodsb    ; Get char from string 
    cmp al, 0 
    je .done   ; If char is zero, end of string 
    int 10h    ; Otherwise, print it 
    jmp short .repeat 

.done: 
    popa 
    ret 


reset_floppy:  ; IN: [bootdev] = boot device; OUT: carry set on error 
    push ax 
    push dx 
    mov ax, 0 
    mov dl, byte [bootdev] 
    stc 
    int 13h 
    pop dx 
    pop ax 
    ret 


l2hts:   ; Calculate head, track and sector settings for int 13h 
      ; IN: logical sector in AX, OUT: correct registers for int 13h 
    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 [Sides] 
    mov dh, dl   ; Head/side 
    mov ch, al   ; Track 

    pop ax 
    pop bx 

    mov dl, byte [bootdev]  ; Set correct device 

    ret 


; ------------------------------------------------------------------ 
; STRINGS AND VARIABLES 

    kern_filename db "KERNEL BIN" ; MikeOS kernel filename 

    disk_error db "Floppy error! Press any key...", 0 
    file_not_found db "KERNEL.BIN not found!", 0 

    bootdev  db 0 ; Boot device number 
    cluster  dw 0 ; Cluster of the file we want to load 
    pointer  dw 0 ; Pointer into Buffer, for loading kernel 


; ------------------------------------------------------------------ 
; END OF BOOT SECTOR AND BUFFER START 

    times 510-($-$$) db 0 ; Pad remainder of boot sector with zeros 
    dw 0AA55h  ; Boot signature (DO NOT CHANGE!) 


buffer:    ; Disk buffer begins (8k after this, stack starts) 


; ================================================================== 

如果它的事項,我在Ubuntu上,使用NASM,並Virtual Box 任何幫助,非常感謝。

回答

0

您沒有創建有效的ISO映像,這可能是Virtualbox拒絕加載它的原因。 您可以使用您創建的軟盤或硬盤映像,或者使用某種工具(如mkisofs)創建適當的可引導iso。

快速瀏覽一下,引導裝載程序需要一個您不會創建的FAT文件系統。你要麼必須改變它,所以它只是加載第二個扇區,或創建一個合適的FAT文件系統。

另請注意,第二次調用dd將覆蓋第一個的輸出(您可以通過檢查文件的大小輕鬆看到該輸出)。