如何在 16 位模式下使用 GDB?

How to use GDB in 16-bit mode?

我有以下代码,我试图在其中实现一个使用 BIOS 函数打印字符串的函数:

int printString(char* string)
{
 int i = 0;
 while (*(string + i) != '[=10=]')
   {
    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 的目标文件。

并且您不能 运行 16 位可执行文件或带有 gdb 的 16 位汇编代码。您必须使用 qemu to run your code on an emulated CPU and connect to it using gdb, or you can use dosbox 之类的东西才能 运行 您的代码,并在 DOS 上使用调试程序。请记住,使用 BIOS 中断在现代 OS 上是错误的,例如 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.imgboot sector.

  • break *0x7c00:第一条指令不会是您的引导扇区,而是 0x0000fff0 执行 BIOS 设置,see also。所以我们使用它从引导扇区加载到的位置开始。
  • set architecture i8086:对于常规的 ELF 可执行文件,GDB 可以根据 headers 决定体系结构。但是对于原始引导扇区,没有这样的元数据,所以我们必须告诉它。

另请参阅: