Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to use GDB in 16-bit mode?

I have the following code, where I am trying to implement a function that prints string using the BIOS functions:

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;
}

The function interrupt is implemented in assembly. It calls the appropriate BIOS interrupt, as given by the first argument, with rest of the arguments containing the contents for ax,bx,cx and dx register respectively:

.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

Since I am using BIOS interrupts I am using 16-bit mode to compile this code. I used the following command:

bcc -ansi -c -o printString.o printString.c

I want to test this code in GDB, but when I try to load this printString.o file into gdb using:

gdb printString.o

I get the following error:

"/home/kern/printString.o": not in executable format: File format not recognized

I also tried changing the GDB to 16-bit format using:

set architecture i8086

But still this error is coming. How can I load a 16-bit code into GDB?

like image 645
sarthak Avatar asked Dec 05 '22 04:12

sarthak


2 Answers

Minimal QEMU example

qemu-system-i386 -hda main.img -S -s &
gdb -ex 'target remote localhost:1234' \
    -ex 'set architecture i8086' \
    -ex 'break *0x7c00' \
    -ex 'continue'

where main.img is a boot sector.

  • break *0x7c00: the first instruction will not be your boot sector, but rather 0x0000fff0 which does the BIOS setup, see also. So we use this to start from where the boot sector gets loaded to.
  • set architecture i8086: for regular ELF executables, GDB can decide architecture from the headers. But for raw boot sectors, there is no such metadata, so we have to tell it.

See also:

  • How to get source level debug info: How to do source level debugging of x86 code with GDB inside QEMU?
  • Similar questions: Low level qemu based debugging || Debug qemu with gdb || Debugging bootloader with gdb in qemu
  • Some more good ideas: https://stackoverflow.com/a/32960272/895245
  • How to step over int: How to step over interrupt calls when debugging a bootloader/bios with gdb and QEMU?

As Jester says in the comments, you cannot run object file with gdb.

And you can not run a 16-bit executable file or 16-bit assembly code with gdb. You must use something like qemu to run your code on an emulated CPU and connect to it using gdb, or you can use dosbox in order to run your code and use a debug program on DOS. And remember, using BIOS interrupts is an error on a modern OS, like Linux, because at start up these operating systems disable BIOS interrupts.

like image 43
Parham Alvani Avatar answered Dec 22 '22 22:12

Parham Alvani