Question

Je suis nouveau dans la conception de systèmes d'exploitation et jusqu'à présent, j'ai conçu un "OS" (en réalité juste un seul secteur de démarrage) et j'ai décidé d'essayer de créer un chargeur de démarrage et un "noyau" distincts (toujours très simples).Ma question est simple, mais a réussi à m'échapper, grâce à Google et à la recherche sur ce site (d'accord, j'ai trouvé une question similaire, mais la réponse était trop vague/avancée pour que je puisse l'utiliser).

J'ai regardé int 0x13 AH=02, mais cela utilise des pistes, ce que je ne pense pas être utilisé par le CD.J'ai vu quelque part que je devrais utiliser un secteur de lecture étendu (AH=0x42), mais je ne vois pas comment l'utiliser, car je ne vois pas où je peux spécifier quel secteur lire et où le secteur doit aller dans la RAM .

Voici la question :Comment charger des secteurs à partir d'un CD qui n'utilise El Torito sans émulation.J'apprécierais que vous puissiez mettre la réponse sous la « forme la plus simple » et essayer de fournir du code, car je suis nouveau dans ce domaine.Merci d'avance!

MODIFIER:

Je ne sais pas si vous en avez besoin, mais j'utilise la syntaxe NASM, donc si vous pouviez me donner la réponse en NASM, ce serait génial.

Était-ce utile?

La solution

Par convention, le BIOS place le numéro de lecteur que vous devez utiliser pour int 13h dans le registre DL.Ensuite, vous pouvez utiliser int 13h, ax=4B01h (obtenir l'état de l'émulation) pour déterminer les informations sur le disque, et la fonction int 13x 42h pour lire les secteurs de CD de taille 0x800 avec le numéro de secteur dans le champ LBA.Vérifier la Chargeur de démarrage ISOLINUX pour plus de détails.Le point d'entrée est _start, la routine de lecture des secteurs est getlinsec_cdrom.

Modifier:lire La documentation sur les extensions int 13h pour savoir comment l'utiliser.Fondamentalement, vous devez transmettre une structure remplie, avec le numéro de secteur, le nombre et l'adresse du tampon où placer les données lues.

Autres conseils

Mon chargeur de démarrage pense qu'il est chargé à 0x07C0: 0x000 plutôt que 0x0000: 0x7c00.Mais ça marche.J'utilise des outils GNU.

C'est l'assemblage:


/**
 * 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

C'est le maquillage:

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

La clé est de comprendre comment Seg: Décalage représente l'adresse en mode réel.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top