Реальный режим Простая сложность ОС

Я пишу простую ОС в реальном режиме ASM для удовольствия. Недавно я решил перейти к файловой системе. Я собрал код с

nasm -f bin -o boot.o boot.asm
nasm -f bin -o kernel.o kernel.asm
nasm -f bin -o fs.o fs.asm

dd if=boot.o bs=512 of=os.img
dd if=kernel.o bs=512 of=os.img seek=1
dd if=fs.o bs=512 of=os.img seek=2

В моем загрузчике я загружаю файловую систему по адресу 0x1000: 0000, а мое ядро ​​- по адресу 0x2000: 0000. Каждый по 512 байт (пока что) довольно мало. Итак, чтобы протестировать мою новую файловую систему, я написал ядро, которое выводит первую букву имени первого файла в таблице. Он помещает значение 0x2000 в si, перемещает байт по адресу в si в al. Затем он передает 0x0e в ah и вызывает int 0x10. Затем он останавливается. Однако, когда я загружаю ос в qemu, он просто показывает мне информацию о BIOS, говорит о загрузке с дискеты, а затем ничего не делает. Нет письма. Ничего такого. Вот соответствующий код:

соответствующий код загрузчика

    ;;the part that loads the file system.
    ;;The part for the kernel is identical, except that cl is 02 and bx is 0x2000
    mov ah, 02
    mov al, 01
    mov ch, 00
    mov cl, 03
    mov dh, 00
    mov dl, 00
    mov bx, 0x1000
    mov es, bx
    xor bx, bx
    int 0x13
    ;;jumps to address 0x2000 (where the kernel is)
    mov ax, 0x2000
    mov ds, ax
    mov es, ax
    mov fs, ax
    mov gs, ax
    mov ss, ax
    xor ax, ax
    jmp 0x2000
    ;;halts
    hlt

соответствующий код ядра

    ;;gets address
    mov si, 0x1000
    ;;loads al
    mov al, [si]
    ;;prints
    mov ah, 0x0e
    int 0x10
    ;;halts
    hlt

соответствующий код файловой системы

    ;;declares first file (it is hard coded for testing purposes)
    ;;format: [name], [sector number], [number of sectors to load]
    db 'file.bin', 4, 1

Если я сделал что-то неприятное при публикации этого сообщения, пожалуйста, простите меня, так как это мой первый пост.


person Kpuonyer    schedule 04.09.2013    source источник


Ответы (1)


В вашем коде есть несколько проблем.

  1. Вы загружаете свою файловую систему по адресу 0x1000:0000. В переводе на линейный адрес (что является наиболее важной формой) это 0x10000, или просто 64 КБ.
  2. Вы загружаете ядро ​​по адресу 0x2000:0000 (0x20000, 128KiB). Прыжок, который ты делаешь

    jmp 0x2000
    

    является переходом относительно IP, поэтому вы не попадете в нужную позицию. Выполнение этого перехода выполняется путем добавления непосредственного значения, переданного в качестве параметра инструкции, к значению регистра IP, который содержит (в это время) адрес следующей инструкции (ваш hlt). Что вам нужно сделать, так это прыгнуть вдаль. Он переходит к абсолютному адресу. Форма дальнего прыжка следующая:

    jmp segment:offset
    

    Замените прыжок, который у вас есть, на этот:

    jmp 0x2000:0000
    
  3. Код ядра, который должен печатать символ, использует регистр SI, использует адресацию относительно сегментов, поскольку вы выполняете свой код в реальном режиме. В отличие от переходов по IP, вы не можете передавать значение со знаком в качестве смещения (хотя это было бы круто и иногда полезно). Измените значение сегмента DS или используйте переопределение сегмента, чтобы все было быстрее. В вашем случае я бы рекомендовал использовать сегмент fs для всех манипуляций с файловой системой, чтобы не было необходимости сохранять и восстанавливать значение ds.

    mov ax, 0x1000
    mov fs, ax
    xor si, si
    mov al, byte [fs:si] ;or simply [fs:si] without byte
    

    Помните, что ds - это сегмент по умолчанию для всех адресов, кроме BP. Вы должны использовать его для основных целей ядра (он сэкономит несколько байтов и, конечно же, будет быстрее). es, fs и gs здесь для вас для других операций с памятью. Вы можете использовать es для обработки адресатов, fs для файловой системы и gs для указания видеопамяти. Все зависит от вас.

Обратите внимание, что некоторые инструкции (movs, cmps, _24 _...) имеют заранее назначенные комбинации регистров и сегментов (и иногда только один из них может быть переопределен), поэтому будьте мудры при их выборе и внимательны при их использовании.

person user35443    schedule 05.09.2013
comment
Ой! Я совершенно упустил из виду, что его прыжок к ядру был недалеко (другой сегмент). Хороший улов! - person Frank Kotler; 06.09.2013
comment
Усилия, затраченные на ответы для этого тега, обычно не важны; OP каким-то образом получает решение и забывает его здесь. Кстати, я заметил, что мы неоднократно встречаемся друг с другом в вопросах сборки / osdev. - person user35443; 06.09.2013
comment
Ага, я знаю, что это устарело, но я просто хотел сказать, что так и не нашел своего собственного ответа, я использовал ваш, ребята. Я отстой в этом. Спасибо за попытку. - person Kpuonyer; 19.10.2015
comment
@Kpuonyer Не-а ... Теперь мы разобрались. - person user35443; 23.10.2015