문제

나는 OS 디자인에 새로운 것이고, 지금까지 하나의 "OS"(정말 단일 부츠)를 설계하고, 별개의 부트 로더와 "커널"(여전히 매우 간단한)을 만들기로 결정했다. 나의 질문은 간단하지만, 아직 끈적 끈적하고,이 사이트를 검색하고, 나는이 사이트를 찾고, 나는 유사한 질문 하나를 찾았지만, 나는 그것을 사용할 수 있도록 모호한 / 진보 된 대답이었습니다. int 0x13 ah= 02를 보았지만 CD의 사용을 생각하지 않는 트랙을 사용합니다. 나는 확장 된 읽기 섹터 (ah= 0x42)를 사용해야하는 어딘가에서 보았지만 읽을 수있는 섹터를 지정할 수 있는지, 섹터가 RAM으로 가야 하는지를 보지 못하기 때문에 나는 그것을 사용하는 방법을 보지 못합니다. .

다음은 다음과 같습니다. El Torito No 에뮬레이션을 사용하는 CD에서 섹터를로드하려면 어떻게합니까? 나는 당신이 '가장 단순한 형태'로 답을 쓸 수 있고, 이것을 새로운 코드를 제공하려고 노력할 수 있다면 감사합니다. 미리 감사드립니다!

편집 :

나는 당신이 그것을 필요로하는지 모르지만, NASM 구문을 사용하고 있으므로 NASM에서 대답을 줄 수 있다면 그것은 위대합니다.

도움이 되었습니까?

해결책

컨벤션별로 BIOS는 int 13h에 사용해야하는 드라이브 번호를 DL 레지스터에 넣습니다.그런 다음 int 13h, ax= 4b01h (에뮬레이션 상태 가져 오기)를 사용하여 디스크 정보를 확인하고 int 13x 함수 42h를 LBA 필드의 섹터 번호로 0x800 크기의 CD 섹터를 읽을 수 있습니다.자세한 내용은 isolinux 부트 로더 EnterPoint는 _start이며, 읽기 섹터를 읽는 루틴은 getlinsec_cdrom입니다.

편집 : 읽기 설명서 int 13h 확장 방법사용해.기본적으로 읽기 데이터를 넣을 수있는 버퍼의 섹터 번호, 카운트 및 주소로 채워진 구조를 전달해야합니다.

다른 팁

My Boot Loader는 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
.

키는 SEG의 방법을 이해하는 것입니다. 오프셋은 실제 모드에서 주소를 나타냅니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top