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.