我目前正在学习引导加载程序开发和使用GDB进行调试,以观察在实模式下禁用A20线时的内存变化。由于 QEMU 自动启用 A20 线,我尝试使用
int 15
中断来禁用它。我有一个引导加载程序 (boot.S),我正在尝试使用 GDB 进行调试。
我已经在
.gdbinit
中设置了调试环境,然后在 make debug
中启动了 GDB。但是,当我尝试单步执行代码时,遇到错误“找不到当前函数的边界”。这种情况在执行第 18 行 (boot.S) 的 int
指令后尤其会发生。
我知道我在这里做错了(我的汇编代码技能仍在发展),但我不知道它是什么:(
启动.S
BOOT_SIGNATURE = 0xAA55
A20_TEST_VALUE = 0x3773
ES_EDGE_ADDR = 0xFFFF
ES_OFFSET_ADDR = 0x0010
.code16
.global start
start:
xorw %ax, %ax
cli
cld
movw %ax, %ds
movw %ax, %ss
movw %ax, %es
movw $0x2400, %ax
int $0x10
call check_a20_status
jmp .
check_a20_status:
xorw %ax, %ax
movw %ax, %ds
movw %ax, %es
movw %ax, %cx
movw $ES_EDGE_ADDR, %ax
movw $ES_OFFSET_ADDR, %bx
movw %ax, %es
movw $A20_TEST_VALUE, %es:(%bx)
movw %ds:0x0, %ax
ret
signature_padding:
.space 510 - (. - start)
.word BOOT_SIGNATURE
生成文件
CC = gcc
CFLAGS = -nostartfiles -nostdlib -m32 -e start -g
LFLAGS = -Wl,-Ttext=0x7c00 -Wl,--build-id=none -Wl,--oformat=binary
BOOT_BIN = -o boot.bin
BOOT_SRC = boot.S
GDB_PORT=3773
obj:
gcc -nostartfiles -nostdlib -m32 -e start -g -Wl,-Ttext=0x7c00 -o boot.out boot.S
image: obj
$(CC) $(CFLAGS) $(LFLAGS) $(BOOT_BIN) $(BOOT_SRC)
debug: image
qemu-system-i386 -drive file=boot.bin,format=raw -nographic -serial mon:stdio -gdb tcp::$(GDB_PORT) -S
gdb:
gdb -n -x .gdbinit
clean:
rm -rf *.bin *.out
.gdbinit
set architecture i8086
target remote localhost:3773
symbol-file boot.out
我在一个终端中使用命令
make debug
启动了 qemu,然后使用命令 make gdb
在另一个终端中启动了 gdb。我在这里附上了 gdb 输出的屏幕截图
任何有关如何解决此问题的见解或建议将不胜感激。谢谢!
movw $0x2400, %ax int $0x10
您需要在
int 15h
处使用“禁用 A20 登机口”服务。您错误地调用了视频 BIOS 服务中断int 10h
。
xorw %ax, %ax cli cld movw %ax, %ds movw %ax, %ss movw %ax, %es
如果要更改 SS 段寄存器,则还要设置 SP 堆栈指针。假设 SS:SP 之前有效并且 SP 包含一个小数字,那么省略初始化 SP(就像您所做的那样)将使 SS:SP 指向中断向量表内。任何进一步使用堆栈(通过
int
,...)都将开始破坏中断向量!
cli
cld
xorw %ax, %ax
movw %ax, %ds
movw %ax, %es
movw %ax, %ss
movw $0x7C00, %sp
movw $0x2400, %ax
int $0x15