Der folgende Text beschreibt wie man auch unter Windows einen Floppy-Boot-Sektor debuggen kann. Dazu braucht man die folgenden Programme.
- Editor
- Ein einfacher Editor, der auch ein bisschen Syntax einfärben kann, ist Notepad++.
- Terminal
- Ein brauchbares Terminal, das auch in der Lage ist, Tabs anzuzeigen ist ConEmu. Man benötigt meistens vier Fenster: Emulator, Monitor, Debugger und Compiler.
- Assembler
- Um einen Boot-Sektor debuggen zu können, muss man ihn erst einmal erzeugen. Das geht mit NASM ganz gut.
- Emulator
- Am einfachsten kann man einen Boot-Sektor in einem Emulator debuggen. Der wohl mächtigste Emulator ist Qemu. Fertige Binaries für Windows gibt es bei Stefan Weil.
- Debugger
- Qemu arbeitet am besten mit dem GNU Debugger GDB zusammen. Fertige Binaries für Windows gibt es bei Equation Solution.
Wie man die Programme installiert und die PATH-Variable setzte dürfte vermutlich jedem klar sein, der Boot-Sektoren debuggen will, weshalb ich darauf nicht weiter eingehe.
Boot-Sektor
Somit stellt sich als nächstes die Frage, wie ein Boot-Sektor erstellt werden kann. Das Geheimnis des Boot-Sektors ist relativ schnell erzählt. Es sind 512 Bytes Code, an deren Ende sich die Bytes 55h und AAh befinden. Da Intel den Speicher im Little-Endian-Format organisiert handelt es sich um das 16 Bit-Wort AA55h. Der Boot-Sektor wird vom BIOS an die Adresse 7C00 geladen und ausgeführt. Beim Start steht CS auf 0 und IP auf 7C00. Free Source Codes shows two example boot sectors: one doing nothing and one printing some dots on the the screen. This is the listing of the one printing dots.
     1                                   _Text SEGMENT PUBLIC USE16
     2          ******************       warning: ignoring unknown section attribute: "USE16"
     3                                  ;************************************************************
     4                                  ; Program entry point
     5                                  ; Currently we are at 0:7C00
     6                                  ;************************************************************
     7                                  org 0
     8                                  EntryPoint:
     9                                      ; Would have preferred 07C0:0000
    10                                      ; Dealing with an offset that starts at 0 is easier
    11                                      ; So do a far jump to 07C0:????
    12                                  
    13 00000000 EA[2700]C007                jmp 0x07C0:AfterData
    14                                  
    15                                  ; Your Data goes here!
    16 00000005 57656C636F6D652074-         BOOT_MSG db 'Welcome to BOOT SECTOR CODE!',10,13,0
    17 0000000E 6F20424F4F54205345-
    18 00000017 43544F5220434F4445-
    19 00000020 210A0D00           
    20 00000024 2E2000                      ACTIVITY db '. ',0
    21                                  
    22                                  AfterData:
    23                                  ; update DS to be 7C0 instead of 0
    24 00000027 0E                      push CS
    25 00000028 1F                      pop DS
    26                                  
    27                                  ; update ES also
    28 00000029 0E                      push CS
    29 0000002A 07                      pop ES
    30                                  
    31                                  ; create stack
    32 0000002B B80000                  mov ax, 0x0000
    33 0000002E 8ED0                    mov ss, ax
    34 00000030 BCFFFF                  mov sp, 0xFFFF
    35                                  
    36                                  ; display boot message...
    37 00000033 8D36[0500]              lea si, [BOOT_MSG]
    38 00000037 E81500                  call Print
    39                                  
    40                                  ; Go into a hang printing dots
    41                                  DIE_LOOP:
    42 0000003A 8D36[2400]              lea si, [ACTIVITY]
    43 0000003E E80E00                  call Print
    44 00000041 B9FFFF                  mov cx, 0xffff
    45                                  delay1:
    46 00000044 BBFF0F                  mov bx, 0xfff
    47                                  delay2:
    48 00000047 4B                      dec bx
    49 00000048 75FD                    jnz delay2
    50 0000004A 49                      dec cx
    51 0000004B 75F7                    jnz delay1
    52 0000004D EBEB                    jmp DIE_LOOP
    53                                  
    54                                  ;************************************************************
    55                                  ; Procedure print
    56                                  ; prints a zero terminated string pointed to by si
    57                                  ;************************************************************
    58                                  Print:
    59 0000004F 50                      push ax
    60 00000050 B40E                    mov ah, 14 ; BIOS code for screen display
    61 00000052 FC                      cld
    62                                  print_loop:
    63 00000053 AC                      lodsb ; moving the character to be displayed to al
    64 00000054 08C0                    or al, al ; checking if the char is NULL
    65 00000056 7404                    jz printdone
    66 00000058 CD10                    int 10h ; Calling BIOS routine
    67 0000005A EBF7                    JMP print_loop
    68                                  
    69                                  printdone:
    70 0000005C 58                      pop ax
    71 0000005D C3                      ret
    72                                  ; End of print procedure...
    73                                  
    74                                  
    75                                  ; Make the file 512 bytes long
    76 0000005E 00<rept>                TIMES 510-($-$$) DB 0 
    77                                  
    78                                  ; Add the boot signature
    79 000001FE 55AA                    dw 0AA55h
Das obige Listing entsteht beim übersetzten des Quelltextes:
nasm boot.asm -l boot.lst -o boot.bin
Debug-Emulation
Der Boot-Sektor kann direkt von Qemu als Floppy-Image zum booten verwendet werden. Wenn man das aktuelle Terminal durch den Aufruf von Qemu nicht blockieren will, kann man sich ein Batch-Script machen und Qemu mit "start /b" starten.
start /b qemu-system-i386 -gdb tcp:127.0.0.1:1234 -monitor telnet:127.0.0.1:1235,server,nowait -S -localtime -fda boot.bin -boot a -no-fd-bootchk
Die Option -gdb öffnet Port 1234 und ermöglicht den Remote-Zugriff durch den Debugger. Das geht im GDB mit folgendem Befehl.
target remote localhost:1234
Und die Option -monitor ermöglicht es mit Telnet auf den Qemu-Monitor zugreifen zu können.
telnet localhost 1235
Da die virtuelle Maschine über die Option -S im gestoppten Modus gestartet wurde, muss man im GDB das System mit c erst starten. Wenn alles richtig funktioniert, werden im Qemu-Fenster der Reihe nach einzelne Punkte ausgegeben.

 
