Beiträge anzeigen

Diese Sektion erlaubt es dir alle Beiträge dieses Mitglieds zu sehen. Beachte, dass du nur solche Beiträge sehen kannst, zu denen du auch Zugriffsrechte hast.


Nachrichten - misterunknown

Seiten: [1]
1
Es ist Real-Mode-Assembler-Code. Reicht das nicht, um als komisch und idiotisch durchzugehen? :-D
Vermutlich, aber für die ersten Schritte in einer virtuellen Maschine sollte das reichen^^ Mein Ziel ist es nicht ein Betriebssystem oder einen vollwertigen Bootloader zu schreiben, sondern mein grundsätzliches Verständnis für das Zusammenspiel von Software und Hardware auszubauen.
2
Auf den ersten Blick: Wenn du mit jmp (bzw. je) nach LineBreak springst, dann kommst du mit ret nicht zurück. Was passiert ist, dass er dein gepushtes 0xd vom Stack nimmt und als Rücksprungadresse benutzt.
Das ergibt natürlich Sinn -.- Offensichtlich ist "call" und "jmp" in meinem Kopf das gleiche gewesen.

Ich habe mir jetzt soetwas gebaut:
Linebreak:
    mov ah,0x0E     ; Print-Funktion nutzen (0x0e)
    mov al,0x0A     ; Zeilenumbruch ausgeben
    int 0x10        ; Interrupt auslösen
    mov al,0x0D     ; Zeilenvorschub ausgeben
    int 0x10        ; Interrupt auslösen
    jmp Main

Main:
    mov ah,00h      ; auf Tastendruck warten
    int 0x16        ; Interrupt auslösen
    cmp al,0x1B     ; ESC gedrückt?
    je  Ende        ;   => zum Ende springen
    cmp al,0x0D     ; Enter gedrückt?
    je  Linebreak   ;   => Zeilenumbruch (0x0A) ausgeben
    mov ah,0x0E     ; Print-Funktion einstellen
    int 0x10        ; Interrupt auslösen
    jmp Main        ; Main-Schleife
Und es funktioniert! Vielen Dank  8-)

Sollte dir oder jemand anderem beim anschauen meines Programms sonst noch auf etwas koschmisches/idiotisches aufgefallen sein bin ich für Tipps dankbar :)
3
Moin,

um etwas Assembler zu lernen habe ich mir (mit einigen Anleitungen für ganz simple Bootloader) ein kleines bootfähiges Programm geschrieben, welches 3 Sachen macht:
  • einen Text ausgeben
  • in einer Schleife alle Tastatureingaben ausgeben
  • wenn ESC gedrückt wird noch einen Text ausgeben und beenden
Das funktioniert auch, bis auf dass die Enter-Taste nur einen Carriage Return ausgibt und keinen Zeilenumbruch macht. Das wollte ich ändern, indem ich prüfe, ob die Enter-Taste gedrückt wurde und wenn ja, erst der Zeilenumbruch ausgegeben wird (0x0A) und dann im Anschluss der Carriage Return (0x0D). Hier ein Ausschnitt:
Linebreak:
    mov ah,0x0E     ; Print-Funktion nutzen (0x0e)
    mov al,0x0A     ; Zeilenumbruch ausgeben
    int 0x10        ; Interrupt auslösen
    ret

Main:
    mov ah,00h      ; auf Tastendruck warten
    int 0x16        ; Interrupt auslösen
    cmp al,0x1B     ; ESC gedrückt?
    je  Ende        ;   => zum Ende springen
    push ax         ; ax sichern (al = 0x0D)
    cmp al,0x0D     ; Enter gedrückt?
    je  Linebreak   ;   => Zeilenumbruch (0x0A) ausgeben
    pop ax          ; ax wiederherstellen (damit sollte al wieder 0x0D sein)
    mov ah,0x0E     ; Print-Funktion einstellen
    int 0x10        ; Interrupt auslösen
    jmp Main        ; Main-Schleife

Das funktioniert nur so lange, bis man Enter drückt. Ist das der Fall wird nur der Zeilenumbruch ausgegeben (0x0A), und dann friert das Programm ein. Ich habe nach einigem hin- und herprobieren keine Idee mehr, was ich falsch mache. Ich habe auch keine Idee, wie ich das debuggen könnte, und hoffe jetzt, dass ihr mir helfen könnt.

Noch einige Informationen zu meinen Tools: Ich nutze zum Kompilieren nasm und zum Testen qemu:
$ nasm -f bin boot.asm -o boot.img
$ qemu-system-x86_64 -fda boot.img

Hier ist der vollständige Code:

;****************************************
; boot.asm - Einfacher Bootloader
;
; 2016 - marco@misterunknown.de
;****************************************

BITS 16             ; 16-Bit Real-Mode

org     0x7C00      ; Wir werden vom BIOS an diese Adresse geladen.


Start:  jmp Loader  ; Loader

msga    db  "Testausgabe",10,13,0
msgb    db  13,10,13,10,"Ende",13,10,0

;**************************************
; Funktionen
;**************************************

Print:
    lodsb           ; lädt das nächste Byte von SI nach AL
    or  al,al       ; ist AL null?
    jz  PrintDone   ; wenn ja, dann gehe zu PrintDone
    mov ah,0x0E     ; Print-Funktion nutzen (0x0e)
    int 0x10        ; Interrupt auslösen
    jmp Print       ; Rücksprungmarke aufrufen

PrintDone:
    ret

Linebreak:
    mov ah,0x0E     ; Print-Funktion nutzen (0x0e)
    mov al,0x0A     ; Zeilenumbruch ausgeben
    int 0x10        ; Interrupt auslösen
    ret

;**************************************
; Loader
;**************************************

Loader:
    xor ax,ax       ; schneller Weg um das Register zu nullen
    mov al,03h      ; in den Text-Modus wechseln (löscht gleichzeitig den Bildschirm)
    int 0x10        ; Interrupt auslösen

    mov si,msga     ; Nachricht in source-Register laden
    call Print      ; Print-Funktion aufrufen

;**************************************
; Hauptschleife
;**************************************

Main:
    mov ah,00h      ; auf Tastendruck warten
    int 0x16        ; Interrupt auslösen
    cmp al,0x1B     ; ESC gedrückt?
    je  Ende        ;   => zum Ende springen
    push ax         ; ax sichern (al = 0x0D)
    cmp al,0x0D     ; Enter gedrückt?
    je  Linebreak   ;   => Zeilenumbruch (0x0A) ausgeben
    pop ax          ; ax wiederherstellen (damit sollte al wieder 0x0D sein)
    mov ah,0x0E     ; Print-Funktion einstellen
    int 0x10        ; Interrupt auslösen
    jmp Main        ; Main-Schleife

Ende:
    mov si,msgb
    call Print
    cli             ; Interrupts leeren
    hlt             ; System anhalten

times 510 - ($ - $$) db 0   ; Das Programm muss 512 Bytes groß werden. Dazu wird mit Nullen aufgefüllt.
                            ; 510 kommt daher, weil hinten noch die 2 Byte lange Signatur folgt.
dw  0xAA55          ; Signatur des Bootloaders

; vim: syn=nasm
Seiten: [1]

Einloggen