Assembly BIOS INT 10,AH=0E第二阶段的奇数行为
我已经开发了大约一年的内核,只是使用GRUB作为引导加载程序。然而,现在我想为我的内核开发一个引导加载程序 尽管我做出了努力,但我似乎无法解决装载机第二阶段的奇怪问题 生成文件:Assembly BIOS INT 10,AH=0E第二阶段的奇数行为,assembly,x86-16,bootloader,osdev,sanity-check,Assembly,X86 16,Bootloader,Osdev,Sanity Check,我已经开发了大约一年的内核,只是使用GRUB作为引导加载程序。然而,现在我想为我的内核开发一个引导加载程序 尽管我做出了努力,但我似乎无法解决装载机第二阶段的奇怪问题 生成文件: BOOTLOADER_FOLDER := boot KERNEL_FOLDER := kernel BOOTLOADER_SOURCES := $(shell find $(BOOTLOADER_FOLDER) -type f -iname "*.asm") BOOTLOAD
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
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
我希望这只是打印
加载…
并停止系统。但是,它会打印以下内容:☺ 您的错误是stage1_address dw 0x500
,它将其声明为内存中的数据字,但随后您继续将其用作符号。将其更改为stage1\u地址eq 0x500
学习使用反汇编程序和调试器。这通常意味着ds
段寄存器值和org
之间不匹配。如果您的数据正在执行,这意味着您跳到了错误的第2阶段。在这两种情况下,都要使用调试器。提供包括第一阶段在内的所有代码以及如何构建磁盘映像都会很有帮助。@MichaelPetch我有一个第一阶段,它使用BIOS将第二阶段从磁盘加载到地址0x0000:0x0500编辑:我将上载第一阶段;没有看到你的评论。@MichaelPetch我使用QEMU@JonathonReinhart:我不推荐QEMU/GDB用于实模式调试,尤其是在调试任何软件中断的情况下。QEMU在这方面严重缺乏支持,因为它不理解20位段:偏移寻址。使用0x0000以外的段将完全混淆GDB。我建议只使用Bochs,它实际上有一个能够理解实模式的调试器,并且对实模式有适当的调试支持。如果您理解QEMU/GDB的缺陷,那么这是可能的(我写了一篇关于这个主题的长篇大论),谢谢您的帮助,我非常感谢!
[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