BIOS INT 10, AH=0E странное поведение на втором этапе

Я разрабатывал свое ядро ​​около года, просто используя GRUB в качестве загрузчика. Тем не менее, теперь я хочу промокнуть в процессе разработки загрузчика для моего ядра.

Несмотря на мои усилия, я не могу решить причудливую проблему со вторым этапом загрузчика.

Makefile:

BOOTLOADER_FOLDER       := boot
KERNEL_FOLDER           := kernel

BOOTLOADER_SOURCES      := $(shell find $(BOOTLOADER_FOLDER) -type f -iname "*.asm")
BOOTLOADER_OBJECTS      := $(subst .asm,.bin,$(BOOTLOADER_SOURCES))

BOOTLOADER_IMAGE        := $(BOOTLOADER_FOLDER)/boot.img

KERNEL_SOURCES          := $(shell find . -type f -iname "*.c")
KERNEL_OBJECTS          := $(foreach x,$(basename $(C_SOURCES)),$(x).o)

OS_IMAGE                := os.img

ALLFILES                := $(BOOTLOADER_SOURCES) $(KERNEL_SOURCES)

NASM                    := nasm
NASM_FLAGS              := -f bin

DD                      := dd
DD_FLAGS                := bs=512

GCC                     := GCC
GCC_FLAGS               := -g -std=gnu99 -Wall -Wextra -pedantic -Wshadow -Wpointer-arith \
                           -Wcast-align -Wwrite-strings -Wmissing-prototypes -Wmissing-declarations \
                           -Wredundant-decls -Wnested-externs -Winline -Wno-long-long \
                           -Wconversion -Wstrict-prototypes

QEMU                    := qemu-system-i386
QEMU_FLAGS              := -fda

all: clean compile todo run

clean:
    -rm -r $(BOOTLOADER_OBJECTS) $(KERNEL_OBJECTS) $(BOOTLOADER_IMAGE) $(OS_IMAGE)

compile: $(BOOTLOADER_OBJECTS) $(KERNEL_OBJECTS)

%.bin:%.asm
    @$(NASM) $(NASM_FLAGS) $< -o $@

%.o:%.c
    @$(GCC) $(GCC_FLAGS) -o $@ $<

$(BOOTLOADER_IMAGE):$(BOOTLOADER_OBJECTS)
    @$(foreach file,$(BOOTLOADER_OBJECTS),dd bs=512 if=$(file) >> $(BOOTLOADER_IMAGE);)

$(KERNEL_IMAGE):$(KERNEL_OBJECTS)

$(OS_IMAGE):$(BOOTLOADER_IMAGE) $(KERNEL_IMAGE)
    @$(DD) $(DD_FLAGS) if=$(BOOTLOADER_IMAGE) >> $(OS_IMAGE)

run:$(OS_IMAGE)
    @DISPLAY=:0 \
    $(QEMU) $(QEMU_FLAGS) $(OS_IMAGE);

todo:
    -@for file in $(ALLFILES:Makefile=); do fgrep -H -e TODO -e FIXME $$file; done; true

stage1.asm:

[BITS 16]
[ORG 0x7C00]

jmp 0x0:main

print_string:
    lodsb
    or      al, al
    jz      .done
    mov     ah, 0x0E
    int     0x10
    jmp     print_string
.done:
    ret

loading_message db "Loading bootloader...", 0xD, 0x0A, 0x0
stage1_address  dw 0x500

reset_disk:
    mov     ah, 0x0
    mov     dl, 0x0

    int     0x13

    jc      reset_disk
    jmp     .done
.done:
    ret

read_disk:
    mov     ah, 0x02

    int     0x13

    cmp     ah, 0x0
    jmp     .done

    cmp     ah, 0x80
    jmp     .try_again
.try_again:
    pusha
    call    reset_disk
    popa

    jmp     read_disk
.done:
    ret

main:
    cli
    xor     ax, ax
    mov     ds, ax
    mov     es, ax
    mov     fs, ax
    mov     gs, ax

    mov     ax, 0x0000
    mov     ss, ax
    mov     sp, 0xFFFF
    sti

    mov     si, loading_message
    call    print_string

    call    reset_disk

    mov     al, 0x1
    mov     ch, 0x0
    mov     cl, 0x2
    mov     dh, 0x0
    mov     dl, 0x0

    mov     bx, stage1_address

    call    read_disk

    jmp     0x000:stage1_address

    cli
    hlt

TIMES 510-($-$$) db 0
db 0x55
db 0xAA

stage2.asm:

[BITS 16]
[ORG 0x500]

jmp main

print_string:
    lodsb
    or      al, al
    jz      .done
    mov     ah, 0x0E
    int     0x10
    jmp     print_string
.done:
    ret

loading_message     db  "Loading...", 0x0

main:
    mov     si, loading_message
    call    print_string

    cli
    hlt

Я ожидал, что это просто напечатать Loading... и остановите систему. Тем не менее, он печатает это: ☺↕Loading... В моих усилиях исправить это, я переместил декларацию loading_message до того, как print_string, К моему удивлению, он дает другой вывод: ссылка

Первоначально я думал, что строка как-то запускается как код, но это невозможно, так как я перепрыгиваю через нее. Тем не менее, я добавил разделители новой строки в строку, и он, кажется, переключает режимы видео (?), Когда объявлено ранее print_string ( ссылка) При объявлении в позиции во фрагменте кода ничего не выводится. Так что, должно быть, это выполняется как код?

Есть идеи, почему это происходит?

(Если вы хотите увидеть любой другой файл или разборки, не стесняйтесь спрашивать!)

1 ответ

Решение

Ваша ошибка stage1_address dw 0x500 который объявляет его как слово данных в памяти, но затем вы продолжаете использовать его как символ. Изменить это на stage1_address equ 0x500,

Научитесь использовать дизассемблер и отладчик.

Другие вопросы по тегам