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.