如何在16位模式下使用GDB?
问题描述:
我有下面的代码,在这里我想实现,使用BIOS功能打印字符串的函数:如何在16位模式下使用GDB?
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中断,由第一个参数作为给定的,具有包含用于斧头,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中?
答
最小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
是boot sector。
-
break *0x7c00
:第一条指令不会是你的引导扇区,而是0x0000fff0
这确实BIOS设置,see also。所以我们使用这个从引导扇区被加载到的地方开始。 -
set architecture i8086
:对于普通的ELF可执行文件,GDB可以从头文件中决定体系结构。但对于原始引导扇区,没有这样的元数据,所以我们必须告诉它。
参见:
- 如何获得源代码级调试信息:How to do source level debugging of x86 code with GDB inside QEMU?
- 类似的问题:Low level qemu based debugging || Debug qemu with gdb || Debugging bootloader with gdb in qemu
- 一些更多的好点子:https://*.com/a/32960272/895245
- 如何跨过
int
:How to step over interrupt calls when debugging a bootloader/bios with gdb and QEMU?
你不能在'gdb'运行的目标文件,无论有多少位。您需要制作可执行文件,如错误消息所述。对于16位代码,您还需要16位环境,例如'qemu'。 – Jester 2015-03-02 14:15:13
@Jester但它在32位模式下使用gcc。命令'gcc -g program.c -o programname'用于生成一个目标代码,并使用'gdb programname'运行。 – sarthak 2015-03-02 15:07:19
是的,现在用两条命令行来“发现差异”。请注意''gcc'没有**具有'-c'并生成可执行文件(也被缺少的'.o'扩展名所暗示),但是''bcc''确实**具有'-c'(这意味着编译为对象)并且输出具有'.o'扩展名。 – Jester 2015-03-02 15:08:06