Tengo el siguiente código, donde intento implementar una función que imprime una cadena usando las funciones del BIOS:
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;
}
La función de interrupción se implementa en ensamblador. Llama a la interrupción de BIOS apropiada, como lo indica el primer argumento, y el resto de los argumentos contienen los contenidos para los registros ax, bx, cx y dx respectivamente:
.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
Como estoy usando interrupciones de BIOS, estoy usando el modo de 16 bits para compilar este código. Utilicé el siguiente comando:
bcc -ansi -c -o printString.o printString.c
Quiero probar este código en GDB, pero cuando trato de cargar este archivo printString.o en gdb usando:
gdb printString.o
Obtuve el siguiente error:
“/home/kern/printString.o”: no en formato ejecutable: formato de archivo no reconocido
También intenté cambiar el formato GDB a 16 bits usando:
set architecture i8086
Pero todavía viene este error. ¿Cómo puedo cargar un código de 16 bits en GDB?
Ejemplo mínimo de QEMU
qemu-system-i386 -hda main.img -S -s &
gdb -ex 'target remote localhost:1234' \
-ex 'set architecture i8086' \
-ex 'break *0x7c00' \
-ex 'continue'
donde main.img
es un sector de arranque.
break *0x7c00
: la primera instrucción no será su sector de arranque, sino más bien 0x0000fff0
que hace la configuración del BIOS, consulte también. Entonces usamos esto para comenzar desde donde se carga el sector de arranque.
set architecture i8086
: para ejecutables ELF normales, GDB puede decidir la arquitectura a partir de los encabezados. Pero para los sectores de arranque sin procesar, no existen tales metadatos, por lo que tenemos que informarlo.
Ver también:
- Cómo obtener información de depuración de nivel de fuente: ¿Cómo hacer la depuración de nivel de fuente del código x86 con GDB dentro de QEMU?
- Preguntas similares: depuración basada en qemu de bajo nivel || Depurar qemu con gdb || Depuración del gestor de arranque con gdb en qemu
- Algunas buenas ideas más: https://stackoverflow.com/a/32960272/895245
- como pasar por encima
int
: ¿Cómo pasar por alto las llamadas de interrupción al depurar un gestor de arranque/bios con gdb y QEMU?
Como dice Jester en los comentarios, no puede ejecutar un archivo de objeto con gdb
.
Y no puede ejecutar un archivo ejecutable de 16 bits o un código ensamblador de 16 bits con gdb
. Debes usar algo como qemu
para ejecutar su código en una CPU emulada y conectarse a ella usando gdb
o puedes usar dosbox
para ejecutar su código y usar un programa de depuración en DOS. Y recuerde, el uso de interrupciones de BIOS es un error en un sistema operativo moderno, como Linux, porque al iniciarse, estos sistemas operativos desactivan las interrupciones de BIOS.
No puede ejecutar archivos de objetos en
gdb
, no importa cuántos bits. Debe crear un ejecutable, como dice el mensaje de error. Para el código de 16 bits, también necesitará un entorno de 16 bits, comoqemu
.– bufón
2 de marzo de 2015 a las 14:15
@Jester Pero se usa en modo de 32 bits con gcc. El comando
gcc -g program.c -o programname
se usa para generar un código objeto y se ejecuta usandogdb programname
– Sarthak
2 de marzo de 2015 a las 15:07
Si, ahora juega
spot the difference
con las dos líneas de comando. Note que elgcc
uno hace no tener-c
y produce ejecutable (también insinuado por la falta.o
extensión) pero subcc
hace tener el-c
(que significa compilar a objeto) y también la salida tiene el.o
extensión.– bufón
2 de marzo de 2015 a las 15:08
@Jester ok … También intenté vincular usando el comando ld86. Pero sigue mostrando el mismo error. ¿Ld86 no produce código ejecutable? ¿No hay otra forma de convertir el archivo .o en ejecutable y usarlo en GDB?
– Sarthak
2 de marzo de 2015 a las 15:21
ld86 produce un ejecutable, pero ese es un ejecutable de 16 bits que no puede cargar en su sistema operativo nativo (que no especificó, pero supongo que Linux). Para el sistema operativo, eso no califica como ejecutable. Es por eso que necesita algo que pueda ejecutar su código de 16 bits y proporcionar los servicios de BIOS esperados. Esto es lo que
qemu
,bochs
odosbox
puede hacer.– bufón
2 de marzo de 2015 a las 15:24