Минимальный рабочий пример источник:
use16
org 0x7c00
jmp 0x0000:@start
@start:
cli
mov ax,cs
mov ds,ax
mov es,ax
mov ss,ax
mov sp,0x7c00
sti
mov bp,sp
call @fails
jmp @start
@fails:
nop
retn
times 510-($-$$) db 0
dw 0xAA55
Выше собрана в двоичный файл через FASM или NASM и записана в MBR VHD (x.vhd). QEMU запускается с включенной поддержкой отладки: qemu-system-i386.exe -m 512 -boot c -net nic -net user -hda x.vhd -no-acpi -s -S -cpu 486
В Cygwin , с GDB 9.1-1 , затем выдаются следующие команды для запуска GDB и присоединения к QEMU, определите архитектуру, пропустите код B IOS и установите точку останова в начале MBR, загруженную в 0x7c00, перед продолжением:
gdb
target remote localhost:1234
set architecture i8086
stepi 11
break *0x7c00
continue
nexti 10
В этот момент $ ip находится в nop
строка.
@fails:
nop ; <---
retn
Здесь возникает проблема. Используя stepi
, временная точка останова помещается в строку retn
, выполнение продолжается до nop
и прерывается там, где и должно. Использование stepo
или nexti
, однако выполнение продолжается без проблем, но точка останова не достигается . ГБД просто вступает в бесконечное ожидание. Если точка останова вставляется вручную после nop
(например, retn
или jmp @start
, инструкция, к которой вызов возвращается с retn
), GDB прерывается на этом без проблем. Перечисление всех точек останова на этом этапе не приводит к появлению новых, поэтому, похоже, nexti
нигде не установил временную точку останова (или временные точки останова не указаны?).
После большого исследования, вот странные "исправления" для проблемы , позволяющие nexti
автоматически просто пропустить nop
и прорваться туда как следует: (1) set $ebp = 0x7bfa
, а затем nexti
или (2) закомментируйте строку mov bp,sp
.
Вопросы:
- Почему
nexti
, кажется, нарушает механизм останова в этом конкретном месте? Возможно, точка останова ставится между инструкциями? Или у nexti
есть проблемы с 16-битным кодом? - Почему работают странные "исправления", описанные выше? Как $ ebp вообще может быть связан с чем-либо, если он не используется ни в какой точке после инициализации? GDB использует это внутренне?