2016-03-16 8 views
5

の第2のセクターをロードするようにブートローダーを有効にします。私は単純なブートローダーを書いた。テストした後、動作しませんでした。簡単なプログラムは、このコマンドを使用してUSBの第2セクタにロードされている私はアセンブリ言語を勉強していますUSB

dd if=f:\boot.bin of=\\.\d: bs=512 count=1 

[bits 16] 
[org 0x7c00] 

jmp start 

data: 
wolf_wel_msg db 'Welcome to Bootloader!!!',0x0D,0x0A,0 
wolf_kernel_load db 'Loading kernel....',0x0D,0x0A,0 
wolf_error_msg db 'Kernel.bin not found!',0x0D,0x0A,0 
wolf_error_msg1 db 'Press any key to restart..',0 

start: 
     mov si, wolf_wel_msg 
    call wolf_print 

    mov si, wolf_kernel_load 
    call wolf_print 

    pushf 
    stc 

    mov ah,00 
    mov dl,00 
    int 13h 

    read_sector: 
      mov ax, 0x0 
     mov es, ax 
     xor bx, bx 
      mov ah, 02 
     mov al, 01 
     mov ch, 01 
     mov cl, 02 
     mov dh, 00 
     mov dl, 00 
     int 13h 

    jc wolf_error 
    popf 
    jmp 0x0:0x1000 
    cli 
    hlt 

    wolf_error: 
      mov si, wolf_error_msg 
     call wolf_print 
     mov si, wolf_error_msg1 
     call wolf_print 
      mov ah,00 
     int 16h 
     xor ax,ax 
     int 19h 

    wolf_print: 
      lodsb 
     or al,al 
     jz exit 
     mov ah,0x0e 
     int 10h 
     jmp wolf_print 
     exit: 
      ret 

times 510-($-$$) db 0 
dw 0xAA55 

このコードは、このコマンドを使用してUSBの最初のセクタに配置されています。ここに私のコードです:

dd if=f:\hello.bin of=\\.\d: bs=512 seek=1 count=1 

これは第2のセクタにロードされたプログラムのためのコードである:

[bits 16] 
[org 0x1000] 

jmp start 
data: 
    msg db 'Hello',0 
start: 
    mov si, msg 
    jmp print 

    cli 
    hlt 
    print: 
     lodsb 
     or al, al 
     jz exit 
     mov ah,0x0e 
     int 10h 
     jmp print 
    exit: 
     ret 

はなぜ私のブートローダが動作していませんか?私は何か間違ったことをした?助言がありますか?

+0

何を試しましたか?正確に「うまくいかない」とは何ですか?出力はまったく得られますか? – Yexo

+0

いいえ「kernel.binが見つかりません」という出力が表示されます。つまり、キャリーが設定されている(失敗した)ことを意味します。 –

+0

"hello.bin"はセカンドセクタから読み込まれません。 –

答えて

10

あなたのコードは、あなたがそれを仮定することはできませんDSが0に設定されていることを前提としています。あなたがorg 0x7c00を使用している場合は、あなたのコードの最初の部分は、明示的に0にDSを設定する必要があります。

SS:SPを設定して、スタックの定義を真剣に考えてください。あなたは、既存のものがどこにあるのか、またあなたがしようとしていることを処理するのに十分な大きさであるか分からない。

ブートローダが呼び出される直前に、BIOSはDLレジスタにブートデバイス番号を設定します。ブートドライブからドライブ要求を行うときにあなたのコード内で0にDLを設定すべきではありません。ブートローダが呼び出されたときに、DLに存在する値を使用しているはずです。

あなたはメモリ内に前進することを期待しLODSB命令を使用しているので、方向フラグをクリアするCLD命令を使用する必要があります。方向フラグが正しく設定されているため、必要な方向に明示的に設定する必要がありますので、CLD(前方)またはSTD(後方)に設定する必要があります。

私はGeneral Bootloader Tipsと私StackOverflowの答えでは上記の問題に関するより多くの情報を持っています。

BPBを使用していないので、ブートローダの最初の指示としてjmp startを削除することを強くお勧めします。代わりに、コードの後でブートセクタの署名(0xAA55)の前にデータを移動します。その理由は、ブートローダの最初の命令として表示されるJMP命令に基づいて、一部のBIOSがBPBを見つけようとし、メモリ内のブートローダの一部を上書きして、

はあなたのブートローダはあなたの第二段階は、第2のセクターからロードを開始し、この命令を使用しています。

jmp 0x0:0x1000 

の問題は、あなたが設定ESのセクターを読んだとき:BXこの方法:

read_sector: 
    mov ax, 0x0 
    mov es, ax 
    xor bx, bx 

これはES:BX〜0x0000:0x0000を設定します。これは、あなたのJMPがコードを期待する場所ではないことは明らかです。 にディスクセクタを読み込ませるメモリの場所にES:BXを設定する必要があります。

INT 13h/AH = 02hは、シリンダー/ヘッド/セクター番号を正しく設定する必要があります。セクタの番号は1で始まりますが、シリンダとヘッドはゼロベースです。

あなたに
mov ch, 01 

:ディスクの第2のセクターは、シリンダ0、ヘッド0でセクター2であるあなたのコードでは、シリンダーはあなたが本当に0に設定されなければならないので、このコードが間違っている1の代わりに、0に設定します2番目の段階ではRET命令で終了するため、printを関数として作成しました。 jmp printcall printに変更する必要があります。あなたのコードがあることを変更することができ、私の一般的なブートローダーの先端からのものを含む上記の推奨すべての変更、と

boot.asm

[bits 16] 
[org 0x7c00] 

        ; Use the boot drive number passed to us by BIOS in register DL 
start: 
    xor ax,ax  ; We want a segment of 0 for DS for this question 
    mov ds,ax  ;  Set AX to appropriate segment value for your situation 
    mov es,ax  ; In this case we'll default to ES=DS 
    mov bx,0x8000 ; Stack segment can be any usable memory 

    mov ss,bx  ; This places it with the top of the stack @ 0x80000. 
    mov sp,ax  ; Set SP=0 so the bottom of stack will be @ 0x8FFFF 

    cld   ; Set the direction flag to be positive direction 

    mov si, wolf_wel_msg 
    call wolf_print 

    mov si, wolf_kernel_load 
    call wolf_print 

    pushf 
    stc 

    mov ah,00 
    int 13h 

    read_sector: 
     mov ax, 0x0 
     mov es, ax  ; ES = 0 
     mov bx, 0x1000 ; BX = 0x1000. ES:BX=0x0:0x1000 
         ; ES:BX = starting address to read sector(s) into 
     mov ah, 02  ; Int 13h/AH=2 = Read Sectors From Drive 
     mov al, 01  ; Sectors to read = 1 
     mov ch, 00  ; CH=Cylinder. Second sector of disk 
         ; is at Cylinder 0 not 1 
     mov cl, 02  ; Sector to read = 2 
     mov dh, 00  ; Head to read = 0 
         ; DL hasn't been destroyed by our bootloader code and still 
         ;  contains boot drive # passed to our bootloader by the BIOS 
     int 13h 

    jc wolf_error 
    popf 
    jmp 0x0:0x1000 
    cli 
    hlt 

    wolf_error: 
     mov si, wolf_error_msg 
     call wolf_print 
     mov si, wolf_error_msg1 
     call wolf_print 
     mov ah,00 
     int 16h 
     xor ax,ax 
     int 19h 

    wolf_print: 
     lodsb 
     or al,al 
     jz exit 
     mov ah,0x0e 
     int 10h 
     jmp wolf_print 
     exit: 
     ret 

; Moved the data before the boot signature but after the code 
wolf_wel_msg db 'Welcome to Bootloader!!!',0x0D,0x0A,0 
wolf_kernel_load db 'Loading kernel....',0x0D,0x0A,0 
wolf_error_msg db 'Kernel.bin not found!',0x0D,0x0A,0 
wolf_error_msg1 db 'Press any key to restart..',0 

times 510-($-$$) db 0 
dw 0xAA55 

hello.asm

[org 0x1000] 

jmp start 
data: 
    msg db 'Hello',0 
start: 
    mov si, msg 
    call print  ; print is a function, use CALL instead of JMP 

    cli 
    hlt 
    print: 
     lodsb 
     or al, al 
     jz exit 
     mov ah,0x0e 
     int 10h 
     jmp print 
    exit: 
     ret 

DDコマンドに記載されている情報に基づいてWindowsを使用しているように見えるので、別の問題が発生している可能性があります。 DDあなたは使用していますが、of=\\.\d:はディスク(USBドライブ)の先頭に書き込まないので、ディスク自体の先頭ではなく、D:にあるパーティションに書き込みます。

最新のDDからChrysocomeを使用することをおすすめします。今日の最新は0.6beta3です。このバージョンは、特定のパーティションの先頭からではなく、ドライブの先頭からディスク(またはUSBスティック)に正しくアクセスできるため、このバージョンをお勧めします。これは第1セクターと第2セクターを正しく保管しようとすると重大な問題を引き起こす可能性があります。私はUSBドライブへの書き込みを管理者権限でこれらのコマンドを使用したい最新バージョンでは:あなたの質問に提案されたよう:

dd if=f:\boot.bin od=d: bs=512 count=1 
dd if=f:\hello.bin od=d: bs=512 seek=1 count=1 

これはあなたのUSBドライブがドライブDにある前提としています。 警告:正しいドライブを使用しないと、別のデバイスでデータが失われ、破損する可能性があります。

は、これらのコマンドが正常に動作した場合の出力のようなものになります。

dd if=boot.bin od=d: bs=512 count=1 
rawwrite dd for windows version 0.6beta3. 
Written by John Newbigin <[email protected]> 
This program is covered by terms of the GPL Version 2. 

Device d: is a link to \\?\Device\HarddiskVolume5 \\?\Device\HarddiskVolume5 is a partition on \Device\Harddisk1 
512 100% 
1+0 records in 
1+0 records out 

dd if=hello.bin od=d: bs=512 seek=1 count=1 
rawwrite dd for windows version 0.6beta3. 
Written by John Newbigin <[email protected]> 
This program is covered by terms of the GPL Version 2. 

Device d: is a link to \\?\Device\HarddiskVolume5 \\?\Device\HarddiskVolume5 is a partition on \Device\Harddisk1 
28 5% 
0+1 records in 
0+1 records out 

をこれらのコマンドを発行した後、Windowsが自動的にドライブがもはや適切にフォーマットされていないことを検出することができます。 Windowsのドライブのフォーマットを許可しないでください。ドライブのフォーマットを許可すると、ドライブを再パーティションしてフォーマットします。そうすることで、あなたが書いたブートセクタが破壊されます。プロンプトが表示されたら、表示される可能性のある形式のダイアログボックスをキャンセルします。

システムからUSBドライブを取り外す前に、USBドライブを正しく取り外すことを忘れないでください。正しくアンマウントしないと、データが正しくドライブに書き込まれない可能性があります。あなたは、コマンドプロンプトで以下のコマンドで720Kフロッピーを作成することができBochsの、QEMU、DOSBoxをなどのディスクイメージを作成したい場合は

は:

dd if=/dev/zero of=disk.img bs=1024 count=720  
dd if=f:\boot.bin of=disk.img bs=512 count=1 conv=notrunc 
dd if=f:\hello.bin of=disk.img bs=512 seek=1 count=1 conv=notrunc 

画像ファイルdisk.imgはBochsの、QEMUが利用可能でなければなりません、DOSboxなど、または実際のコンピュータで使用するために720kディスケットに書き込むことができます。

/dev/zeroは、一般的なUnix/Linuxデバイスのようです。 DD Windows用コマンド/dev/zeroをゼロを生成する特別な入力デバイスとして理解することをお勧めします。 Windowsには/dev/zeroデバイスがありませんが、DDは、それを特別な内部デバイスとして認識し、それをシミュレートします。 16ギガバイトのUSBスティックと私のレノボL520ノートパソコン(非EFI BIOS)で

enter image description here

これは次のとおりです。


MS Windows上でBochsの2.6.8で実行すると、これは私が見たものです私が見たもの:

enter image description here

関連する問題