2015-03-02 67 views
3

我有下面的代码,在这里我想实现,使用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中?

+0

你不能在'gdb'运行的目标文件,无论有多少位。您需要制作可执行文件,如错误消息所述。对于16位代码,您还需要16位环境,例如'qemu'。 – Jester 2015-03-02 14:15:13

+0

@Jester但它在32位模式下使用gcc。命令'gcc -g program.c -o programname'用于生成一个目标代码,并使用'gdb programname'运行。 – sarthak 2015-03-02 15:07:19

+0

是的,现在用两条命令行来“发现差异”。请注意''gcc'没有**具有'-c'并生成可执行文件(也被缺少的'.o'扩展名所暗示),但是''bcc''确实**具有'-c'(这意味着编译为对象)并且输出具有'.o'扩展名。 – Jester 2015-03-02 15:08:06

回答

1

正如Jester在评论中所说的,你不能用gdb运行目标文件。

而且你不能运行16位可执行文件或16位汇编代码与gdb。你必须使用类似qemu的东西来在你的代码上运行你的代码并使用gdb来连接它,或者你可以使用dosbox来运行你的代码并在dos上使用调试程序。并记住使用BIOS中断是一个错误是像Linux现代操作系统,因为在启动这些操作系统禁用BIOS中断。

5

最小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可以从头文件中决定体系结构。但对于原始引导扇区,没有这样的元数据,所以我们必须告诉它。

参见: