BITS 16
ORG 100h ; .COM Programm startet bei 0x100
start:
mov dx,msg ; Zeiger auf Nachricht
mov ah,09h ; DOS Funktion - String ausgeben
int 21h ; DOS Interrupt
mov ah,4Ch ; DOS Funktion - Programm beenden
int 21h
msg db 'Hello World from DOS!', '$' ; '$' = String-Ende für DOS
Beispielcode 2 - Hello World
BITS 16
ORG 100h
start:
mov si, text
xor cx, cx
lenloop:
lodsb
cmp al, 0
je lendone
inc cx
jmp lenloop
lendone:
mov ax, cx
shl ax, 1 ; AX = 2 * Länge
mov bx, ax
mov ax, 160
sub ax, bx
mov dx, ax ; DX = Anzahl Bytes, um vom Ende der geschriebenen Zeichen
mov ax, 0B800h
mov es, ax
xor di, di ; Start = Zeile 0, Spalte 0
mov cx, 10 ; Anzahl Zeilen
mov bl, 1 ; Startfarbe (1..F)
printline:
mov si, text
printchar:
lodsb
cmp al, 0
je endline
mov [es:di], al ; Zeichen
inc di
mov [es:di], bl ; Attribut / Farbe
inc di
jmp printchar
endline:
add di, dx ; zum nächsten Zeilenanfang springen
inc bl
cmp bl, 0Fh
jbe skipreset
mov bl, 1
skipreset:
loop printline
mov ax, 4C00h
int 21h
text db 'Hello World !!!', 0
Beispielcode 3 - Hello World
BITS 16
ORG 100h
start:
mov ax, 0B800h ; Textspeicher Adresse für 80x25 Textmodus
mov es, ax
xor di, di ; Start bei Position 0
mov si, text
mov bl, 1 ; Startfarbe (1 = blau auf schwarz)
printloop:
lodsb
cmp al, 0
je done
mov [es:di], al ; Zeichen schreiben
inc di
mov [es:di], bl ; Farbbyte schreiben
inc di
inc bl ; Farbe wechseln
cmp bl, 0Fh
jbe continue
mov bl, 1
continue:
jmp printloop
done:
ret
text db 'Hello World !!!', 0
Beispielcode 4 - Hello World
BITS 16
ORG 100h
start:
mov ax, 0003h ; 80x25 Textmodus sicher aktivieren
int 10h
mov si, text ; Zeiger auf String
mov bl, 1 ; Startfarbe (1 = blau auf schwarz)
mov dh, 10 ; Zeile = 10
mov dl, 10 ; Spalte = 10
mov bh, 0 ; Seite 0
nextchar:
lodsb
test al, al
jz waitkey
mov ah, 02h
int 10h
mov ah, 09h
mov cx, 1
int 10h
inc dl ; Spalte ++
inc bl ; Farbe ++
cmp bl, 0Fh
jbe short nextchar
mov bl, 1
jmp short nextchar
waitkey:
mov ah, 00h
int 16h ; Warten auf Taste
mov ax, 4C00h
int 21h
text db 'Hello World !!!', 0
Beispielcode 5 - Input Texteingabe
BITS 16
ORG 100h ; .COM-Programme starten immer bei Adresse 0100h
start:
mov dx, msg_eingabe ; Adresse des Textes in DX laden
mov ah, 09h ; DOS Funktion 09h = String ausgeben ($-terminiert)
int 21h ; DOS aufrufen für Text wird angezeigt
mov dx, buffer ; Adresse des Eingabepuffers
mov ah, 0Ah ; DOS Funktion 0Ah = Zeileneingabe
int 21h ; DOS liest Text bis ENTER gedrückt wird der Text landet in "buffer"
mov dx, newline ; Zeilenumbruch String in DX
mov ah, 09h
int 21h
mov dx, msg_ausgabe
mov ah, 09h
int 21h
mov si, buffer + 2 ; SI zeigt auf den ersten Buchstaben
mov cl, [buffer + 1] ; CL = tatsächliche Länge der Eingabe
add si, cx ; SI = Ende des Textes
mov byte [si], '$' ; Setze '$' als Endzeichen
mov dx, buffer + 2 ; Zeiger auf Textanfang
mov ah, 09h
int 21h
mov ax, 4C00h ; DOS-Funktion 4Ch = Programmende
int 21h
msg_eingabe db 'Bitte Text eingeben: $'
msg_ausgabe db 'Du hast eingegeben: $'
newline db 13,10,'$'
buffer db 255 ; Maximale Eingabelänge = 255 Zeichen
db 0 ; Tatsächliche Eingabelänge (wird von DOS gesetzt)
times 255 db 0 ; Speicher für Text
Beispielcode 6 - VGA Rechteck Zeichen
org 100h
start:
mov AH,0
mov AL,12h
int 10h
mov AH,0Bh
mov BX,0 ; 0 = Schwarz
int 10h
; Obere Linie
mov word [y_beg],100
mov word [x_beg],100
mov word [y_end],100
mov word [x_end],200
call linie
; Untere Linie
mov word [y_beg],200
mov word [x_beg],100
mov word [y_end],200
mov word [x_end],200
call linie
; Linke Linie
mov word [y_beg],100
mov word [x_beg],100
mov word [y_end],200
mov word [x_end],100
call linie
; Rechte Linie
mov word [y_beg],100
mov word [x_beg],200
mov word [y_end],200
mov word [x_end],200
call linie
call readchar
mov AH,0
mov AL,03h
int 10h
mov AH,4Ch
int 21h
readchar:
mov AH,6
mov DL,0FFh ; ohne warten
int 21h
jz readchar
ret
linie:
mov DX,[y_beg] ; Start Y
mov CX,[x_beg] ; Start X
draw:
mov AL,15
mov AH,0Ch ; VGA Pixel schreiben
int 10h ; DX=Y, CX=X, AL=Farbe
mov AL,0
cmp CX,[x_end]
je row
add CX,1
mov AL,1
row:
cmp DX,[y_end]
je col
add DX,1
mov AL,1
col:
cmp AL,1
jz draw
ret
x_beg dw 0
y_beg dw 0
x_end dw 0
y_end dw 0
org 100h
start:
mov AX,0013h ; 13h = 320x200, 256 Farben
int 10h
mov AH,0Bh
mov BX,9 ; 9 = hellblau
int 10h
mov word [y_beg],50
mov word [x_beg],50
mov word [y_end],150
mov word [x_end],200
call fill_rect
call readchar
mov AH,0
mov AL,03h
int 10h
mov AH,4Ch
int 21h
readchar:
mov AH,6
mov DL,0FFh ; ohne warten
int 21h
jz readchar
ret
fill_rect:
mov DX,[y_beg]
fill_row:
mov CX,[x_beg]
fill_col:
mov AL,14 ; gelb
mov AH,0Ch ; VGA Pixel schreiben
int 10h ; DX=Y, CX=X, AL=Farbe
inc CX
cmp CX,[x_end]
jle fill_col
inc DX
cmp DX,[y_end]
jle fill_row
ret
; Variablen
x_beg dw 0
y_beg dw 0
x_end dw 0
y_end dw 0
Beispielcode 8 - VGA Moving Ball
BITS 16
ORG 100h
start:
mov ax, 0013h ; VGA 320x200, 256 Farben
int 10h
; Anfangsposition
mov bx, 50 ; X
mov dx, 80 ; Y
main_loop:
lea si, [ball]
mov ax, 0A000h
mov es, ax
mov al, 9
call draw_ball
call getkey
cmp al, 'w'
je move_up
cmp al, 'a'
je move_down
cmp al, 'n'
je move_left
cmp al, 'm'
je move_right
cmp al, 27 ; ESC = Ende
je exit_program
jmp main_loop
move_up:
dec dx
jmp main_loop
move_down:
inc dx
jmp main_loop
move_left:
dec bx
jmp main_loop
move_right:
inc bx
jmp main_loop
exit_program:
mov ax, 0003h
int 10h
mov ax, 4C00h
int 21h
draw_ball:
push ax
push bx
push dx
push si
mov cx, 16 ; Höhe
row_loop:
push cx
mov cx, 16 ; Breite
mov di, dx
imul di, 320
add di, bx
draw_pixel:
lodsb
mov [es:di], al
inc di
loop draw_pixel
add si, 0
inc dx
pop cx
dec cx
jnz row_loop
pop si
pop dx
pop bx
pop ax
ret
getkey:
mov ah, 0
int 16h
ret
ball:
db 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
db 0,0,0,0,14,14,14,14,14,14,14,0,0,0,0,0
db 0,0,0,14,14,15,14,14,14,15,14,14,0,0,0,0
db 0,0,14,14,15,12,15,14,15,12,15,14,14,0,0,0
db 0,14,14,15,12,12,12,15,15,12,12,12,15,14,0,0
db 0,14,14,15,12,12,15,14,15,12,12,15,14,14,0,0
db 0,14,14,14,15,15,14,14,14,15,15,14,14,14,0,0
db 0,14,14,14,14,14,14,15,14,14,14,14,14,14,0,0
db 0,14,14,14,14,14,14,15,14,14,14,14,14,14,0,0
db 0,14,14,14,15,15,14,14,14,15,15,14,14,14,0,0
db 0,14,14,15,12,12,15,14,15,12,12,15,14,14,0,0
db 0,14,14,15,12,12,12,15,15,12,12,12,15,14,0,0
db 0,0,14,14,15,12,15,14,15,12,15,14,14,0,0,0
db 0,0,0,14,14,15,14,14,14,15,14,14,0,0,0,0
db 0,0,0,0,14,14,14,14,14,14,14,0,0,0,0,0
db 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
Beispielcode 9 - VGA Text Ausgabe
BITS 16
ORG 100h
start:
mov ax,0013h
int 10h
; Farbe 10 - Rot
mov dx,3C8h
mov al,10
out dx,al
mov dx,3C9h
mov al,63
out dx,al
xor al,al
out dx,al
xor al,al
out dx,al
; Farbe 11 - Grün
mov dx,3C8h
mov al,11
out dx,al
mov dx,3C9h
xor al,al
out dx,al
mov al,63
out dx,al
xor al,al
out dx,al
; Farbe 12 - Blau
mov dx,3C8h
mov al,12
out dx,al
mov dx,3C9h
xor al,al
out dx,al
xor al,al
out dx,al
mov al,63
out dx, al
; Farbe 13 - Gelb
mov dx,3C8h
mov al,13
out dx,al
mov dx,3C9h
mov al,63
out dx,al
mov al,63
out dx,al
xor al,al
out dx,al
; Farbe 15 - Weiß
mov dx,3C8h
mov al,14
out dx,al
mov dx,3C9h
mov al,63
out dx,al
mov al,63
out dx,al
mov al,63
out dx,al
mov ax,0A000h
mov es,ax
mov si,text1
mov bx,20
mov dx,30
mov al,10
call draw_string_color
mov si,text2
mov bx,20
mov dx,50
mov al,11
call draw_string_color
mov si, text3
mov bx,20
mov dx,70
mov al,12
call draw_string_color
mov si,text4
mov bx,20
mov dx,90
mov al,13
call draw_string_color
mov si,text5
mov bx,20
mov dx,110
mov al,14
call draw_string_color
wait_key:
mov ah,0
int 16h
mov ax,0003h
int 10h
mov ax,4C00h
int 21h
draw_string_color:
push ax
push bx
push dx
mov [color],al
nextchar:
lodsb
cmp al, 0
je done
push si
push dx
mov ah, al ; ASCII in AH
call draw_char ; BL enthält immer die Farbe
pop dx
pop si
add bx, 8
jmp nextchar
done:
pop dx
pop bx
pop ax
ret
draw_char:
push ax
push bx
push dx
push di
push si
mov si,font_table
mov al,ah ; ASCII in AL für Font-Index
sub al,32
xor ah,ah
shl ax,3
add si,ax
mov di,dx
imul di,320
add di,bx
mov cx,8
row:
mov al,[si] ; Font-Bit für diese Zeile
inc si
mov bh,8
col:
test al,80h
jz skip
mov bl, [color] ; BL wiederherstellen
mov [es:di], bl
skip:
shl al,1
inc di
dec bh
jnz col
add di,320-8
loop row
pop si
pop di
pop dx
pop bx
pop ax
ret
text1 db "Hallo VGA!!! 0123456789",0
text2 db "Jede Zeile hat eine andere Farbe!",0
text3 db "Palette per OUT 3C8/3C9 gesetzt.",0
text4 db "Fonts aus eigener Tabelle ABC xyz!",0
text5 db "0123456789 !@#$%^&*() []{}<>?",0
color: dw 0
font_table:
db 00000000b,00000000b,00000000b,00000000b,00000000b,00000000b,00000000b,00000000b ; 32 ' '
db 00011000b,00011000b,00011000b,00011000b,00011000b,00000000b,00011000b,00000000b ; 33 '!'
db 00100100b,00100100b,00100100b,00000000b,00000000b,00000000b,00000000b,00000000b ; 34 '"'
db 00100100b,00100100b,11111111b,00100100b,11111111b,00100100b,00100100b,00000000b ; 35 '#'
db 00011000b,00111110b,01011000b,00111100b,00011010b,01111100b,00011000b,00000000b ; 36 '$'
db 01100010b,01100100b,00001000b,00010000b,00100000b,01001100b,10001100b,00000000b ; 37 '%'
db 00110000b,01001000b,00110000b,01101000b,10001100b,10001100b,01110110b,00000000b ; 38 '&'
db 00011000b,00011000b,00010000b,00100000b,00000000b,00000000b,00000000b,00000000b ; 39 '''
db 00001100b,00011000b,00110000b,00110000b,00110000b,00011000b,00001100b,00000000b ; 40 '('
db 00110000b,00011000b,00001100b,00001100b,00001100b,00011000b,00110000b,00000000b ; 41 ')'
db 00000000b,00100100b,00011000b,01111110b,00011000b,00100100b,00000000b,00000000b ; 42 '*'
db 00000000b,00011000b,00011000b,01111110b,00011000b,00011000b,00000000b,00000000b ; 43 '+'
db 00000000b,00000000b,00000000b,00000000b,00011000b,00011000b,00010000b,00100000b ; 44 ','
db 00000000b,00000000b,00000000b,01111110b,00000000b,00000000b,00000000b,00000000b ; 45 '-'
db 00000000b,00000000b,00000000b,00000000b,00011000b,00011000b,00000000b,00000000b ; 46 '.'
db 00000010b,00000100b,00001000b,00010000b,00100000b,01000000b,10000000b,00000000b ; 47 '/'
db 00111100b,01000010b,01000110b,01001010b,01010010b,01100010b,00111100b,00000000b ; 48 '0'
db 00001000b,00011000b,00101000b,00001000b,00001000b,00001000b,00111110b,00000000b ; 49 '1'
db 00111100b,01000010b,00000010b,00011100b,00100000b,01000000b,01111110b,00000000b ; 50 '2'
db 00111100b,01000010b,00000010b,00011100b,00000010b,01000010b,00111100b,00000000b ; 51 '3'
db 00000100b,00001100b,00010100b,00100100b,01111110b,00000100b,00000100b,00000000b ; 52 '4'
db 01111110b,01000000b,01111100b,00000010b,00000010b,01000010b,00111100b,00000000b ; 53 '5'
db 00111100b,01000010b,01000000b,01111100b,01000010b,01000010b,00111100b,00000000b ; 54 '6'
db 01111110b,00000010b,00000100b,00001000b,00010000b,00010000b,00010000b,00000000b ; 55 '7'
db 00111100b,01000010b,01000010b,00111100b,01000010b,01000010b,00111100b,00000000b ; 56 '8'
db 00111100b,01000010b,01000010b,00111110b,00000010b,01000010b,00111100b,00000000b ; 57 '9'
db 00000000b,00011000b,00011000b,00000000b,00011000b,00011000b,00000000b,00000000b ; 58 ':'
db 00000000b,00011000b,00011000b,00000000b,00011000b,00011000b,00010000b,00100000b ; 59 ';'
db 00000100b,00001000b,00010000b,00100000b,00010000b,00001000b,00000100b,00000000b ; 60 '<'
db 00000000b,00000000b,01111110b,00000000b,01111110b,00000000b,00000000b,00000000b ; 61 '='
db 00100000b,00010000b,00001000b,00000100b,00001000b,00010000b,00100000b,00000000b ; 62 '>'
db 00111100b,01000010b,00000100b,00001000b,00010000b,00000000b,00010000b,00000000b ; 63 '?'
db 00111100b,01000010b,01011010b,01010110b,01011110b,01000000b,00111100b,00000000b ; 64 '@'
db 00111100b,01000010b,01000010b,01111110b,01000010b,01000010b,01000010b,00000000b ; 65 'A'
db 01111100b,01000010b,01000010b,01111100b,01000010b,01000010b,01111100b,00000000b ; 66 'B'
db 00111100b,01000010b,01000000b,01000000b,01000000b,01000010b,00111100b,00000000b ; 67 'C'
db 01111100b,01000010b,01000010b,01000010b,01000010b,01000010b,01111100b,00000000b ; 68 'D'
db 01111110b,01000000b,01000000b,01111100b,01000000b,01000000b,01111110b,00000000b ; 69 'E'
db 01111110b,01000000b,01000000b,01111100b,01000000b,01000000b,01000000b,00000000b ; 70 'F'
db 00111100b,01000010b,01000000b,01001110b,01000010b,01000010b,00111100b,00000000b ; 71 'G'
db 01000010b,01000010b,01000010b,01111110b,01000010b,01000010b,01000010b,00000000b ; 72 'H'
db 00111100b,00011000b,00011000b,00011000b,00011000b,00011000b,00111100b,00000000b ; 73 'I'
db 00011110b,00000100b,00000100b,00000100b,00000100b,01000100b,00111000b,00000000b ; 74 'J'
db 01000010b,01000100b,01001000b,01110000b,01001000b,01000100b,01000010b,00000000b ; 75 'K'
db 01000000b,01000000b,01000000b,01000000b,01000000b,01000000b,01111110b,00000000b ; 76 'L'
db 01000010b,01100110b,01011010b,01000010b,01000010b,01000010b,01000010b,00000000b ; 77 'M'
db 01000010b,01100010b,01010010b,01001010b,01000110b,01000010b,01000010b,00000000b ; 78 'N'
db 00111100b,01000010b,01000010b,01000010b,01000010b,01000010b,00111100b,00000000b ; 79 'O'
db 01111100b,01000010b,01000010b,01111100b,01000000b,01000000b,01000000b,00000000b ; 80 'P'
db 00111100b,01000010b,01000010b,01000010b,01001010b,01000100b,00111010b,00000000b ; 81 'Q'
db 01111100b,01000010b,01000010b,01111100b,01001000b,01000100b,01000010b,00000000b ; 82 'R'
db 00111100b,01000010b,01000000b,00111100b,00000010b,01000010b,00111100b,00000000b ; 83 'S'
db 01111110b,00011000b,00011000b,00011000b,00011000b,00011000b,00011000b,00000000b ; 84 'T'
db 01000010b,01000010b,01000010b,01000010b,01000010b,01000010b,00111100b,00000000b ; 85 'U'
db 01000010b,01000010b,01000010b,01000010b,00100100b,00100100b,00011000b,00000000b ; 86 'V'
db 01000010b,01000010b,01000010b,01000010b,01011010b,01111110b,01000010b,00000000b ; 87 'W'
db 01000010b,00100100b,00011000b,00011000b,00011000b,00100100b,01000010b,00000000b ; 88 'X'
db 01000010b,00100100b,00011000b,00010000b,00010000b,00010000b,00010000b,00000000b ; 89 'Y'
db 01111110b,00000010b,00000100b,00001000b,00010000b,00100000b,01111110b,00000000b ; 90 'Z'
db 00111110b,00100000b,00100000b,00100000b,00100000b,00100000b,00111110b,00000000b ; 91 '['
db 10000000b,01000000b,00100000b,00010000b,00001000b,00000100b,00000010b,00000000b ; 92 '\'
db 00111110b,00000010b,00000010b,00000010b,00000010b,00000010b,00111110b,00000000b ; 93 ']'
db 00010000b,00101000b,01000100b,00000000b,00000000b,00000000b,00000000b,00000000b ; 94 '^'
db 00000000b,00000000b,00000000b,00000000b,00000000b,00000000b,00000000b,00000000b ;
db 00000000b,00000000b,00000000b,00000000b,00000000b,00000000b,11111111b,00000000b ; 95 '_'
db 00000000b,00000000b,00111100b,00000010b,00111110b,01000010b,00111110b,00000000b ; 96 'a'
db 01000000b,01000000b,01111100b,01000010b,01000010b,01000010b,01111100b,00000000b ; 97 'b'
db 00000000b,00000000b,00111100b,01000010b,01000000b,01000010b,00111100b,00000000b ; 98 'c'
db 00000010b,00000010b,00111110b,01000010b,01000010b,01000010b,00111110b,00000000b ; 99 'd'
db 00000000b,00000000b,00111100b,01000010b,01111110b,01000000b,00111100b,00000000b ; 100 'e'
db 00001100b,00010010b,00010000b,00111100b,00010000b,00010000b,00010000b,00000000b ; 101 'f'
db 00000000b,00000000b,00111110b,01000010b,01000010b,00111110b,00000010b,00111100b ; 102 'g'
db 01000000b,01000000b,01111100b,01000010b,01000010b,01000010b,01000010b,00000000b ; 103 'h'
db 00010000b,00000000b,00110000b,00010000b,00010000b,00010000b,00111000b,00000000b ; 104 'i'
db 00000100b,00000000b,00000100b,00000100b,00000100b,01000100b,00111000b,00000000b ; 105 'j'
db 01000000b,01001000b,01010000b,01100000b,01010000b,01001000b,01000100b,00000000b ; 106 'k'
db 00110000b,00010000b,00010000b,00010000b,00010000b,00010000b,00111000b,00000000b ; 107 'l'
db 00000000b,00000000b,01100110b,01011010b,01000010b,01000010b,01000010b,00000000b ; 108 'm'
db 00000000b,00000000b,01111100b,01000010b,01000010b,01000010b,01000010b,00000000b ; 109 'n'
db 00000000b,00000000b,00111100b,01000010b,01000010b,01000010b,00111100b,00000000b ; 110 'o'
db 00000000b,00000000b,01111100b,01000010b,01000010b,01111100b,01000000b,01000000b ; 111 'p'
db 00000000b,00000000b,00111110b,01000010b,01000010b,00111110b,00000010b,00000010b ; 112 'q'
db 00000000b,00000000b,01101100b,00010010b,00010000b,00010000b,00010000b,00000000b ; 113 'r'
db 00000000b,00000000b,00111100b,01000000b,00111100b,00000010b,01111100b,00000000b ; 114 's'
db 00010000b,00010000b,00111100b,00010000b,00010000b,00010010b,00001100b,00000000b ; 115 't'
db 00000000b,00000000b,01000010b,01000010b,01000010b,01000010b,00111110b,00000000b ; 116 'u'
db 00000000b,00000000b,01000010b,01000010b,00100100b,00100100b,00011000b,00000000b ; 117 'v'
db 00000000b,00000000b,01000010b,01000010b,01011010b,01111110b,01000010b,00000000b ; 118 'w'
db 00000000b,00000000b,01000010b,00100100b,00011000b,00100100b,01000010b,00000000b ; 119 'x'
db 00000000b,00000000b,01000010b,01000010b,01000010b,00111110b,00000010b,00111100b ; 120 'y'
db 00000000b,00000000b,01111110b,00000100b,00001000b,00010000b,01111110b,00000000b ; 121 'z'
db 00000110b,00001000b,00001000b,00010000b,00001000b,00001000b,00000110b,00000000b ; 122 '{'
db 00011000b,00011000b,00011000b,00000000b,00011000b,00011000b,00011000b,00000000b ; 123 '|'
db 01100000b,00010000b,00010000b,00001000b,00010000b,00010000b,01100000b,00000000b ; 124 '}'
db 00000000b,00000000b,00100010b,01010100b,00001000b,00000000b,00000000b,00000000b ; 125 '~'
Bootloader "Hello World" im 40x25 Textmodus (schwarzer Hintergrund, bunte Schrift)
Zusätzliche Erklärung: Aufbau eines Bootsektors
Ein Bootsektor ist der erste Sektor512 Bytes groß und wird vom BIOS beim Starten direkt in den Speicher bei Adresse 0x7C00 geladen und ausgeführt.
Offset (Hex)
Größe
Inhalt
Beschreibung
0x000 – 0x1BD
446 Bytes
Bootloader Code
Hier befindet sich unser Assembler Programm, z.B. „Hello World“.
0x1BE – 0x1FD
64 Bytes
Partitionstabelle
Nur bei Festplatten wichtig (MBR). Bei einfachen Bootloadern bleibt dieser Bereich leer.
0x1FE – 0x1FF
2 Bytes
0x55AA
Bootsignatur: Das BIOS prüft diese Bytes. Fehlen sie, wird der Datenträger nicht gebootet.
Warum dw 0xAA55 am Ende stehen muss
Die beiden letzten Bytes 0x55 und 0xAA (in dieser Reihenfolge im Speicher) sind die sogenannte Bootsignatur.
Diese ist zwingend erforderlich, damit das BIOS erkennt: „Dieser Sektor ist bootfähig“. Fehlt sie, wird das BIOS einfach die nächste Bootquelle versuchen und dein Code wird nie ausgeführt.
Im Quellcode steht daher am Ende:
times 510-($-$$) db 0 ; Rest des Sektors auffüllen bis 510 Bytes
dw 0xAA55 ; Bootsignatur am Ende
Erklärung:
times 510-($-$$) db 0 → füllt den restlichen Bereich des 512-Byte-Sektors mit Nullen auf.
dw 0xAA55 → schreibt die beiden letzten Bytes 0x55 und 0xAA an Position 0x1FE–0x1FF.
Ohne diese Signatur wird der Stick oder das Image nicht als bootfähig erkannt.
Diese Anleitung zeigt Schritt für Schritt, wie du einen einfachen Bootloader unter Windows erstellst, der:
den Textmodus 40x25 aktiviert
den Bildschirm auf schwarz löscht
in der Mitte "Hello World" anzeigt
jedem Buchstaben eine andere Farbe gibt
Schritt 1: Bootloader 1 Quellcode erstellen
Erstelle eine Datei boot.asm mit folgendem Inhalt:
bits 16
org 0x7C00
start:
cli
xor ax,ax
mov ds,ax
mov es,ax
mov ss,ax
mov sp,0x7C00
sti
; 40x25 Textmodus aktivieren
mov ax,0x0001 ; Modus 1 = 40x25 Text
int 0x10
; Segment für Textspeicher setzen (0xB800)
mov ax,0xB800
mov es,ax
xor di,di
; Bildschirm löschen (40*25)
mov cx,1000 ; 40 Spalten * 25 Zeilen
clear:
mov byte [es:di],0
inc di
mov byte [es:di],0x00 ; schwarzer Hintergrund
inc di
loop clear
; Position: Mitte (Zeile 12, Spalte 14 bei 40 Spalten)
mov si,text
mov cx,text_len
mov bx,0
mov di,(12*40+14)*2
print_loop:
lodsb
mov [es:di],al
mov al,color_table[bx]
mov [es:di+1],al
add di,2
inc bx
cmp bx,color_count
jl skip_reset
xor bx,bx
skip_reset:
loop print_loop
hang:
cli
hlt
jmp hang
text db 'Hello World!'
text_len equ $-msg
; Vordergrundfarben bunt, Hintergrund schwarz (0x0)
color_table db 0x04,0x02,0x06,0x03,0x01,0x05,0x07,0x0E,0x0C,0x0A,0x09,0x0F
color_count equ $-color_table
times 510-($-$$) db 0
dw 0xAA55
fsutil file createnew disk.img 1474560 → erstellt eine neue Datei disk.img mit genau 1.474.560 Bytes (1,44 MB, typische Größe einer Diskette).
copy /b boot.bin + disk.img disk.img → kopiert binär ("/b") zuerst die Inhalte von boot.bin an den Anfang von disk.img, dann den Rest von disk.img wieder hinten dran. So wird die Bootsektor-Datei direkt an den Anfang des Images geschrieben.
Hinweis: Das erzeugte Image ist jetzt bootfähig, solange dein Bootloader korrekt ist und die Bootsignatur 0xAA55 am Ende hat.
Bootloader 2 - Von Real Mode zu Protected Mode
org 0x7C00
bits 16
start:
; NMI deaktivieren
in al,0x70 ; aktuellen CMOS Wert lesen
or al,0x80 ; NMI-Disable Bit setzen
out 0x70,al
cli ; normale Interrupts aus
xor ax,ax
mov ds,ax
mov ss,ax
mov sp,0x7C00
mov es,ax
; Kurz in Real Mode Text ausgeben
mov si,real_text
call print16
; A20 aktivieren
call enable_a20
; Aktuelle Cursor Position merken (Zeile)
mov ah,0x03 ; BIOS - Get cursor position
mov bh,0x00 ; Seite 0
int 0x10
mov [cursor_row],dh
; GDT laden
lgdt [gdt_descriptor]
; Protected Mode aktivieren
mov eax,cr0
or eax,1 ; PE Bit setzen
mov cr0,eax
; NMI wieder aktivieren (optional, kann auch nach PM init kommen)
in al,0x70
and al,0x7F
out 0x70,al
; Far Jump zu Protected Mode Code Segment
jmp 0x08:protected_mode_start
[bits 32]
protected_mode_start:
mov ax,0x10
mov ds,ax
mov es,ax
mov fs,ax
mov gs,ax
mov ss,ax
mov esp,0x90000
; VRAM Adresse für nächste Zeile berechnen
mov edi,0xB8000
movzx eax,byte [cursor_row]
add eax,1 ; nächste Zeile
imul eax,80 ; 80 Spalten
shl eax,1 ; 2 Bytes pro Zeichen
add edi,eax
mov esi, prot_text
call print32
halt:
hlt
jmp halt
; ----------------------
print16:
pusha
print16_loop:
lodsb
test al,al
jz done16
mov ah,0x0E
int 0x10
jmp print16_loop
done16:
popa
ret
print32:
pusha
print32_loop:
lodsb
test al,al
jz done32
mov ah,0x0F
mov [edi],ax
add edi,2
jmp print32_loop
done32:
popa
ret
; ----------------------
enable_a20:
wait_input_empty:
in al,0x64
test al,2
jnz wait_input_empty
mov al,0xD1
out 0x64,al
wait_input_empty2:
in al,0x64
test al,2
jnz wait_input_empty2
mov al,0xDF
out 0x60,al
ret
; ----------------------
cursor_row: db 0
real_text: db "Hello World in Real Mode!",0
prot_text: db "Hello World in Protected Mode!",0
; ----------------------
gdt_start:
dq 0 ; Null Descriptor
gdt_code:
dw 0xFFFF
dw 0x0000
db 0x00
db 10011010b ; Code Segment
db 11001111b
db 0x00
gdt_data:
dw 0xFFFF
dw 0x0000
db 0x00
db 10010010b ; Data Segment
db 11001111b
db 0x00
gdt_end:
gdt_descriptor:
dw gdt_end - gdt_start - 1
dd gdt_start
times 510-($-$$) db 0
dw 0xAA55
Bootloader 2 - Tron (Mini Game)
org 7C00h
start:
xor ax,ax
mov ss,ax
mov sp,0FFFEh
mov ax,07C0h
mov ds,ax
mov es,ax
mov ax,13h ; VGA 320x200, 256 Farben
int 10h
mov ax,0A000h
mov es,ax
call reset_game
main_loop:
mov ax,[player1_y] ; - Spieler 1 Position berechnen und prüfen
mov bx,320
mul bx
add ax,[player1_x]
mov di,ax
mov al,[es:di]
cmp al,0
jne collision_p1 ; nur Spieler 1
mov al,12 ; rot
mov [es:di],al
mov ax,[player2_y] ; - Spieler 2 Position berechnen und prüfen
mov bx,320
mul bx
add ax,[player2_x]
mov di,ax
mov al,[es:di]
cmp al,0
jne collision_p2 ; nur Spieler 2
mov al,9 ; blau
mov [es:di],al
mov ah,01h ; - Tastatur prüfen
int 16h
jz no_key
mov ah,00h
int 16h
cmp ah,4Dh ; Pfeil rechts
je p1_turn_right
cmp ah,4Bh ; Pfeil links
je p1_turn_left
cmp ah,1Eh ; Taste 'A'
je p2_turn_left
cmp ah,2Ch ; Taste 'Y'
je p2_turn_right
no_key:
mov al,[p1_dir] ; - Spieler 1 Bewegung
cmp al,0
je p1_up
cmp al,1
je p1_right
cmp al,2
je p1_down
cmp al,3
je p1_left
p1_up:
dec word [player1_y]
jmp p1_check
p1_right:
inc word [player1_x]
jmp p1_check
p1_down:
inc word [player1_y]
jmp p1_check
p1_left:
dec word [player1_x]
p1_check:
mov ax,[player1_x]
cmp ax,0
jl collision_p1
cmp ax,319
jg collision_p1
mov ax,[player1_y]
cmp ax,0
jl collision_p1
cmp ax,199
jg collision_p1
mov al,[p2_dir] ; - Spieler 2 Bewegung
cmp al,0
je p2_up
cmp al,1
je p2_right
cmp al,2
je p2_down
cmp al,3
je p2_left
p2_up:
dec word [player2_y]
jmp p2_check
p2_right:
inc word [player2_x]
jmp p2_check
p2_down:
inc word [player2_y]
jmp p2_check
p2_left:
dec word [player2_x]
p2_check:
mov ax,[player2_x]
cmp ax,0
jl collision_p2
cmp ax,319
jg collision_p2
mov ax,[player2_y]
cmp ax,0
jl collision_p2
cmp ax,199
jg collision_p2
mov cx,100 ; - Verzögerung in der Spielroutine
outer_delay:
mov dx,60000
inner_delay:
dec dx
jnz inner_delay
dec cx
jnz outer_delay
jmp main_loop
p1_turn_right: ; - Steuerung Player 1
mov al,[p1_dir]
add al,1
and al,3
mov [p1_dir],al
jmp no_key
p1_turn_left:
mov al,[p1_dir]
add al,3
and al,3
mov [p1_dir],al
jmp no_key
p2_turn_right: ; - Steuerung Player 2
mov al,[p2_dir]
add al,1
and al,3
mov [p2_dir],al
jmp no_key
p2_turn_left:
mov al,[p2_dir]
add al,3
and al,3
mov [p2_dir],al
jmp no_key
collision_p1: ; - Kollisions-Explosion nur für Spieler 1
mov bx,[player1_y]
mov cx,[player1_x]
call explode_red
jmp wait_key
collision_p2: ; - Kollisions-Explosion nur für Spieler 2
mov bx,[player2_y]
mov cx,[player2_x]
call explode_blue
jmp wait_key
explode_red: ; - Explosion 5x5 rot
sub bx,2
sub cx,2
mov si,0
expl_row_r:
mov di,bx
imul di,320
add di,cx
mov dx,0
expl_col_r:
mov byte [es:di],12 ; rot statt weiß
inc di
inc dx
cmp dx,5
jl expl_col_r
inc bx
inc si
cmp si,5
jl expl_row_r
ret
explode_blue: ; - Explosion 5x5 blau
sub bx,2
sub cx,2
mov si,0
expl_row_b:
mov di,bx
imul di,320
add di,cx
mov dx,0
expl_col_b:
mov byte [es:di],9
inc di
inc dx
cmp dx,5
jl expl_col_b
inc bx
inc si
cmp si,5
jl expl_row_b
ret
wait_key: ; - Warten auf Tastendruck
mov ah,01h
int 16h
jz wait_key
call reset_game
reset_game: ; - Neustart bei Kollision
xor di,di
mov cx,320*200/2
xor ax,ax
rep stosw
mov word [player1_x],160 ; - Spieler 1 in Mitte rechts starten
mov word [player1_y],100
mov byte [p1_dir],1
mov word [player2_x],159 ; - Spieler 2 in Mitte links starten
mov word [player2_y],100
mov byte [p2_dir],3
jmp main_loop
player1_x dw 0
player1_y dw 0
p1_dir db 0
player2_x dw 0
player2_y dw 0
p2_dir db 0
times 510-($-$$) db 0
dw 0AA55h
Bootloader 3 - Hexdump Track 0 (Sektoren 1-18)
org 7C00h
start:
cli
xor ax,ax
mov ds,ax
mov es,ax
mov ss,ax
mov sp,07C00h
sti
mov ax,1112h ; Load 8x8 Font (VGA)
mov bl,0
int 10h
mov ax,1201h
mov bl,20h
int 10h
mov [BootDrive],dl
mov [SectorNum],byte 1 ; Sektor 1
next_sector:
call cls
mov ah,02h
mov al,1
mov ch,0
mov cl,[SectorNum]
mov dh,0
mov dl,[BootDrive]
mov bx,0500h
int 13h
jc disk_error
mov si,0500h
mov cx,512
xor dx,dx ; Offset im Sektor
dump_loop:
push cx
mov al,'S'
call print_char
mov al,[SectorNum]
call print_sector_dec
mov al,':'
call print_char
push dx
mov ax,dx
call print_hex16
pop dx
mov al,':'
call print_char
mov al,' '
call print_char
push si
mov bx,si
mov cx,16
print_hex_bytes:
lodsb
call print_hex8
mov al,' '
call print_char
loop print_hex_bytes
mov si,bx
mov cx,16
mov al,' '
call print_char
mov al,' '
call print_char
print_ascii:
lodsb
cmp al,20h
jb dot
cmp al,7Eh
ja dot
jmp show
dot:
mov al,'.'
show:
call print_char
loop print_ascii
call newline
pop si
add si,16
add dx,16
pop cx
sub cx,16
jg dump_loop
mov si,info_msg
call print_string
call wait_key_or_exit
inc byte [SectorNum]
cmp byte [SectorNum],19
jl next_sector
hang:
call cls
mov si,final_msg
call print_string
hang1:
jmp hang1
wait_key_or_exit:
mov ah,01h ; BIOS: Prüfen auf Tastendruck
int 16h
jz wait_key ; Wenn keine Taste, wieder warten
mov ah,00h ; BIOS: Taste lesen
int 16h
cmp al,1Bh ; ESC?
je hang
ret
wait_key:
jmp wait_key_or_exit
newline:
mov ah,0Eh
mov al,0Dh
int 10h
mov al,0Ah
int 10h
ret
print_char:
mov ah,0Eh
int 10h
ret
print_hex8:
push ax
push bx
mov bl,al ; AL sichern
mov al,bl
shr al,4 ; oberes Nibble
call nibble_to_ascii
call print_char
mov al,bl
and al,0Fh ; unteres Nibble
call nibble_to_ascii
call print_char
pop bx
pop ax
ret
print_hex16:
push ax
xchg al,ah
call print_hex8
xchg al,ah
call print_hex8
pop ax
ret
nibble_to_ascii:
cmp al,9
jbe num
add al,7
num:
add al,'0'
ret
print_sector_dec:
mov al,[SectorNum] ; AL = Sektor
cmp al,10
jb single_digit ; größer 10 → führende Null
mov ah,al ; Kopie
sub al,10 ; AL = Einerstelle
mov al,ah ; Zehnerstelle = 1
mov al,'1'
call print_char
mov al,[SectorNum]
sub al,10 ; Einerstelle = AL - 10
add al,'0'
call print_char
ret
single_digit:
mov al, '0'
call print_char ; führende Null
mov al, [SectorNum]
add al, '0'
call print_char
ret
print_string:
next:
lodsb
or al,al
jz done
call print_char
jmp next
done:
ret
cls:
mov ah, 06h
mov al, 0
mov bh, 07h
mov cx, 0000h
mov dx, 314Fh ; Zeile 49 (0x31), Spalte 79 (0x4F) bei 50 Zeilen
int 10h
mov ah, 02h ; - Cursor nach oben links
xor bh, bh
xor dh, dh
xor dl, dl
int 10h
ret
disk_error:
mov si,err_msg
call print_string
jmp hang
BootDrive db 0
SectorNum db 0
err_msg db 'Disk read error!',0
info_msg db 'Press any key to continue!',0
final_msg db 'Finsih !!!',0
times 510-($-$$) db 0
dw 0AA55h