2012-03-13 7 views
2

私はOS設計には新しく、これまでは1つの "OS"(実際にはただ1つのブートセクタ)を設計しており、別個のブートローダと "カーネル" 。私の質問はシンプルですが、グーグルで私を逃れて、このサイトを検索しています(似たような質問がありましたが、答えは漠然としています。セクタをCDからロードする

私はint 0x13 AH = 02を見ましたが、それはトラックを使用していますが、私はそれがCDを使用していないと考えています。私はどこかで、拡張読み込みセクタ(AH = 0x42)を使うべきだと思っていたが、どのセクタを読み込むかを指定することができないため、どのように使用するのか分からない。

ここでは、「El Torito no emulationを使用するCDからセクタをロードするにはどうすればよいですか?あなたが答えを「最も単純な形式」にして、これを初めて使ったときにいくつかのコードを提供しようとすると感謝します。前もって感謝します!

EDIT:

あなたがそれを必要とする場合、私は知らないが、私はNASMの構文を使用していますので、あなたは私のNASMで答えを与えることができれば、それは素晴らしいことです。

+0

他の質問へのリンクが便利ですか? – sarnold

+0

ここをクリック:http://stackoverflow.com/questions/856050/how-to-load-kernel-into-memory-from-cd-rom-using-assembly-nasm – Codesmith

+0

20年前は、しかし、私は確かにCD-ROMドライブの読み取りをサポートする1​​6ビットBIOSは決してないと確信しています。 –

答えて

3

BIOSは、慣例として、intレジスタ13hに使用するドライブ番号をDLレジスタに格納します。次に、int 13h、ax = 4B01h(エミュレーションステータスを取得)を使用してディスク情報を確認し、LBAフィールドのセクタ番号を持つ0x800サイズのCDセクタを読み取るint 13x関数42hを使用できます。詳細については、ISOLINUX bootloaderをご確認ください。エントリーポイントは_startで、セクターを読み取るルーチンはgetlinsec_cdromです。

編集:それを使用する方法については、the documentationをint 13h拡張子で読んでください。基本的には、読み込みデータを格納するバッファのセクタ番号、カウント、およびアドレスを含む塗りつぶされた構造体を渡す必要があります。

+0

2つの疑問は、セクターをどこに置くべきかCPUにどのように伝えるのですか?私はES:BXなどを使用しますか?また、これは16ビットリアルモードで動作しますか? – Codesmith

+0

また、コンピュータにどのセクタを読み込ませるのかを教えてください。それはまだClですか? – Codesmith

+0

編集後に完璧です。ありがとう! – Codesmith

0

私のブートローダは、0x0000:0x7c00ではなく0x07c0:0x000にロードされていると考えています。しかし、それは動作します。私はGNUツールを使用しています。


/** 
* This is the first stage bootloader. It is used to loader the second 
* stage bootloader. 
*/ 



# The address of this bootloader been loaded by BIOS 
.equ BOOTLOADER_ADDR, 0x07c0 

# The signature for bootloader. 
.equ BOOT_MACHINE_SIGNATURE, 0xaa55 

# The offset of the start of BPB (BIOS Parameter Block). 
.equ BOOT_MACHINE_BPB_START, 0x03 

# The offset of the end of BPB (BIOS Parameter Block). 
.equ BOOT_MACHINE_BPB_END, 0x5a 

# The offset of the end of the partition table. 
.equ BOOT_MACHINE_PART_END, 0x1fe 

/* The segment of disk buffer. The disk buffer MUST be 32K long and 
    cannot straddle a 64K boundary. */ 
.equ BOOT_MACHINE_BUFFER_SEG, 0x7000 

.macro PRINT str 
     pusha 
     movw $\str, %si 
     call print 
     popa 
.endm 

.macro DUMP begin, size 
     movw $\begin, %si 
     movw $\size, %cx 
     call dump 
.endm 

.macro RESET_DISK drive 
     pusha 
     movb $\drive, %dl 
     movw 0x0, %ah 
     call reset_disk 
     popa 
.endm 

.macro READ_SECTORS drive, head, cylinder, sector, count, destination 
     pusha 
     movw $\destination, %ax 
     movw %ax, %es 
     xorw %bx, %bx 
     movb $\drive, %dl 
     movb $\head, %dh 
     movb $\cylinder, %ch 
     movb $\sector, %cl 
     movb $\count, %al 
     call read_sectors 
     popa 
.endm 

/** 
* Entry point 
*/ 
     .file "boot.S" 
     .text 
     .code16 
     .org 0x0000 
.globl _start, start; 
_start: 
start: 
# The offset 0x0000 must be a jump to the reset of code. 
     jmp after_BPB 
     nop 
     . = _start + BOOT_MACHINE_BPB_START 
     . = _start + 4 
disk_addr_packet: 
     .byte 0x10    # (00h) size of packet 
     .byte 0x00    # (01h) reserved 
     .word 0x0001   # (02h) number of blocks to transfer 
     .word 0x8000, 0x0000 # (04h) DWORD, transfer buffer 
     .word 0x0010, 0x0000 # (08h) QWORD, starting absolute block number 
     .word 0x0000, 0x0000 
           # (10h) 
     . = _start + BOOT_MACHINE_BPB_END 
after_BPB: 
     cli        # disable interrupt. 
     movw $BOOTLOADER_ADDR, %ax  # set address expression 
     movw %ax, %ds 
     movw %ax, %es 
     # movw $BOOTLOADER_ADDR, %sp # stack grows down to 0x0000 
     PRINT message_booting 

# We need make sure the BIOS supports the INT 13 extensions. 
int13_ext_check: 
     mov $0x41, %ah 
     mov $0x55aa, %bx 
     # DL should contain the drive value. But we'd better save it. 
     push %dx 
     int $0x13 
     jc int13_ext_check_failed 
     cmpw $0xaa55, %bx 
     jne int13_ext_check_failed 
     andw $0x001, %cx  # if function 42h-44h,47h,48h are supported 
     jz int13_ext_check_failed 
     jmp read_cd_content 

int13_ext_check_failed: 
     PRINT message_no_int13_ext 
     jmp loop 

read_cd_content: 

     # CHS mode : Cylinder-Head-Sector mode. 
     # LBA mode : Logical Block Addressing mode. 
     # When we use INT 13 extension, we use LBA mode in which 
     # the device is taken as a single large device. 

     PRINT message_loading_img 
     pop %dx 
     movw $disk_addr_packet, %si 
     movb $0x42, %ah 
     int $0x13 
     jc error_read_sectors 

     DUMP 0x0400, 16 
     jmp loop 

error_read_sectors: 
     PRINT message_sector_read_err 
     jmp loop 
loop: 
     PRINT message_halt 
     cli 
     hlt 
     jmp loop 
message_booting: 
     .asciz "Booting ...\r\n" 
message_halt: 
     .asciz "Boot Halt.\r\n" 
message_no_int13_ext: 
     .asciz "No INT13 extension. Boot failed.\r\n" 
message_loading_img: 
     .asciz "Loading OS image.\r\n" 
message_sector_read_err: 
     .asciz "Sector read error.\r\n" 
hexdump: 
     .byte 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08 

/** 
* Write the string pointed to by %si 
* Each char is wrote by using BIOS INT 0x10. 
* BIOS INT 0x10: 
* AH = 0x0e 
* AL = Character to write. 
* BH = Page Number (Should be 0) 
* BL = Foreground color (Graphics Modes Only) 
* When using the function, put the string address to SI. The string 
* should end with 0. 
*/ 
1: 
     movw $0x0001, %bx 
     movb $0xe, %ah 
     int $0x10 
print: 
     lodsb # Loads a byte pointed by SI into AL. 
     cmpb $0, %al 
     jne 1b 
     ret 

/** 
* Print the register's value. 
* 
print_reg: 

/** 
* Dump a area of data. 
* Display 8 bytes of code each line. For every 10 line will wait for any key to continue. 
* SI = The start address 
* CX = The size of area to dump 
*/ 
index: 
.byte '0', '1', '2', '3', '4', '5', '6', '7', '8', '9' 
.byte 'A', 'B', 'C', 'D', 'E', 'F' 
enter_key: 
.asciz "\r\n" 
1: 
     ret 
dump: 
     movb $10, %dl   # DL = row counter, DH = column counter. 
     movb $8, %dh 
     cld 
2: 
     cmpw $0, %cx 
     je 1b 
     xorw %ax, %ax   # clean the AX at first. 
     lodsb     # loads the byte pointed by SI into AL. 
     push %ax    # because AH will be used, so we save AX. 
     shr $4, %ax    # show first 4 bits. 
     movw $index, %di 
     addw %ax, %di 
     movb (%di), %al 
     movb $0xe, %ah 
     movw $0x0001, %bx  # Page number = 0, froeground color = 1. 
     int $0x10 
     pop %ax 
     andw $0x000f, %ax  # show last 4 bits. 
     movw $index, %di 
     addw %ax, %di 
     movb (%di), %al 
     movb $0xe, %ah 
     movw $0x0001, %bx 
     int $0x10 
     movb $' ', %al   # display a space 
     movb $0xe, %ah 
     movw $0x0001, %bx 
     int $0x10 
     dec %cx 
     dec %dh 
     jnz 2b 
     PRINT enter_key 
     movb $8,%dh 
     jmp 2b 

/** 
* Reset the disk controller, let it go to the first sector. 
* BIOS INT 0x13 
* AH = 0x00 
* DL = Drive to reset. 
* Return: 
* AH = Status code. 
* CF = Clear if success, set if failure. 
*/ 
reset_disk: 
     int $0x13 
     jc reset_disk 
     ret 

/** 
* Read sectors into memory 
* BIOS INT 0x13 
* AH = 0x02 
* AL = Numbers of sectors to read. 
* CH = Low eight bits of cylinder number. 
* CL = Sector Number Bits 0-5. Bits 6-7 are for hard disks only. 
* DH = Head number. 
* DL = Drive number (Bit 7 set for hard disk) 
* ES:BX = Buffer to read sector to 
* Return 
* AH = Status code 
* AL = Number of sectors read 
* CF = Set if failure, cleaned if successful. 
*/ 
read_sectors: 
     int $0x13 
     jc read_sectors 
     ret 

     .fill 0x1fe - (. - _start) ,1,0 
     .org _start + BOOT_MACHINE_PART_END 
     .word BOOT_MACHINE_SIGNATURE 

これはMakefileのである:リアルモードのアドレスを表しオフセット:

 
all: 
     i686-elf-as -o boot.o boot.S 
     i686-elf-ld --oformat=binary -Ttext=0x0 -o boot.bin boot.o 

# Make fd is for test only, our target media is CD. 
fd: all 
     dd status=noxfer conv=notrunc if=boot.bin of=floppy.flp 
     qemu-system-i386 -fda floppy.flp 

cd: all 
     mkdir -p iso/boot 
     cp boot.bin iso/boot/loader.sys 
     mkisofs -R -J -c boot/bootcat \ 
       -b boot/loader.sys -no-emul-boot -boot-load-size 4 \ 
       -input-charset utf-8 \ 
       -o ./boot.iso ./iso 
     qemu-system-i386 -cdrom boot.iso 

clean: 
     @rm -rf iso boot.o boot.bin floppy.flp boot.iso 

キーがワンセグを理解している

この

はアセンブリです。

+0

多くのBIOSは、ジャンプする場所として0x0000:0x7c00を使用します。このようなジャンプは、CS = 0x0000およびIP = 0x7c00を設定する。いくつかのBIOS(QEMUのBIOSを含む)は0x07c0:0x0000にジャンプし、CS = 0x07c0とIP = 0x0000になります。 –

+0

0x07c0:0x0000 =(0x07c0 << 4)+0 = 0x07c00物理アドレス。 0x0000:0x7c00 =(0x0000 << 4)+ 7c00 = 0x07c00物理アドレス。どちらも同じ場所にマップされます。 BIOSは0x07c00にマップされているセグメントにジャンプできます。 (したがって、_CS_を特定の値にすることはできません)ブートローダのコードは、_CS_(もちろん_DS_、_ES_)の値に依存するべきではありません。あなたのコードに必要なものだけを設定する必要があります。使用するセグメントは原点/オフセットに依存します(-Tテキストによって決定されます)。 -Ttext = 0は_DS_が0x07c0に設定されている必要があります。 -Ttext = 0x7c00は、_DS_が0であることを要求します。 –

+0

絶対的な間接ジャンプに近いブートローダコードを書いたことがある場合(あなたのコードはそれを指摘していない)、CSは実際に正しく設定する必要があります。これは通常、コード内のラベルに遠くジャンプすることによって行われます。コード* _after_BPB *に、 'jmp $ BOOTLOADER_ADDR、$ .mainjmp'の後ろに' .mainjmp: 'というラベルを付けることができます。これは文字通り次の命令に飛びつくでしょう。副作用は今_CS_がBOOTLOADER_ADDR(0x07c0)になるということです。あなたが書いたコードには当てはまりません。どのように興味があるかも知れないCSを特定の値に設定する –

関連する問題