如何在16位模式下使用GDB?
我有以下代码,我试图实现一个使用BIOS函数打印字符串的函数:
int printString(char* string) { int i = 0; while (*(string + i) != '\0') { char al = *(string + i); char ah = 0xe; int ax = ah * 256 + al; interrupt(0x10,ax,0,0,0); i++; } return i; }
函数中断在汇编中实现。 它调用适当的BIOS中断,如第一个参数所给出的,其余参数分别包含ax,bx,cx和dx寄存器的内容:
.global _interrupt _interrupt: push bp mov bp, sp push si push ds mov ax, #0x100 mov ds, ax mov ax, [bp + 0x4] mov si, #intr mov [si + 1], al pop ds mov ax, [bp + 0x6] mov bx, [bp + 0x8] mov cx, [bp + 0xa] mov dx, [bp + 0xc] intr: int #0x0 pop si pop bp ret
由于我使用BIOS中断,我使用16位模式来编译此代码。 我使用以下命令:
bcc -ansi -c -o printString.o printString.c
我想在GDB中测试这段代码,但是当我尝试使用以下命令将此printString.o文件加载到gdb中时:
gdb printString.o
我收到以下错误:
“/home/kern/printString.o”:不是可执行格式:无法识别文件格式
我还尝试使用以下方法将GDB更改为16位格式:
set architecture i8086
但是这个错误仍然存在。 如何将16位代码加载到GDB中?
正如Jester在评论中所说,你不能用gdb
运行目标文件。
并且您无法使用gdb
运行16位可执行文件或16位汇编代码。 你必须像qemu
一样在模拟cpu上运行代码并使用gdb
连接到它,或者你可以使用dosbox
来运行代码并在dos上使用调试程序。 并记住使用BIOS中断是一个错误是现代操作系统像Linux,因为在启动时这些操作系统禁用BIOS中断。
最小的QEMU示例
qemu-system-i386 -hda main.img -S -s & gdb -ex 'target remote localhost:1234' \ -ex 'set architecture i8086' \ -ex 'break *0x7c00' \ -ex 'continue'
其中main.img
是引导扇区 。
-
break *0x7c00
:第一条指令不是你的启动扇区,而是执行BIOS设置的0x0000fff0
, 另请参阅 。 因此我们使用它从引导扇区加载到的位置开始。 -
set architecture i8086
:对于常规的ELF可执行文件,GDB可以从头部决定架构。 但是对于原始引导扇区,没有这样的元数据,所以我们必须告诉它。
也可以看看:
- 如何获取源代码级调试信息: 如何在QEMU中使用GDB对x86代码进行源代码级调试?
- 类似问题: 低级qemu调试 || 使用gdb || 调试qemu 在qemu中使用gdb调试引导加载程序
- 一些更好的想法: https : //stackoverflow.com/a/32960272/895245
- 如何跳过
int
: 如何在使用gdb和QEMU调试bootloader / bios时跳过中断调用?