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
,
Научитесь использовать дизассемблер и отладчик.