2015-03-02 72 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可以從頭文件中決定體系結構。但對於原始引導扇區,沒有這樣的元數據,所以我們必須告訴它。

參見: