[ASSEMBLER] Interrupt in Interrupt Tabelle einfügen

AW: [ASSEMBLER] Interrupt in Interrupt Tabelle einfügen

Nur auf der normalen Tastatur. Mit dem Numpad + habe ich jetzt die HDD ganz nach oben gebracht. Hat aber am Problem nichts geändert. Sobald ich "make" eingebe, fängt er an mit dem Erstellen der virtuellen Boot-Diskette für MiniOS an und bricht halt dann irgendwann wieder mit dem Errno 6 bzw. Error 22 ab ... :(

In den Settings scheint jetzt zumindest das richtige File drinnen zu sein:

Capture.JPG

Floppy auf "auto detect" stimmt?
 
Zuletzt bearbeitet:
AW: [ASSEMBLER] Interrupt in Interrupt Tabelle einfügen

Du musst bei Floppy dann aber die Zieldatei auswählen, wenn du auf das Laufwerk zugreifen willst (connect nicht vergessen). Auto detect sucht AFAIK nach einem physischen Laufwerk (falls du noch ein Floppy hast ^^)
 
AW: [ASSEMBLER] Interrupt in Interrupt Tabelle einfügen

^^ Okay, danke! Das hat uns einen großen Schritt weitergebracht ...

Die virtuelle Boot-Diskette wird jetzt richtig geschrieben, aber die Ausgabe in der Testumgebung "MiniOS" stimmt noch nicht:

Capture.JPG

Es soll ja am Ende dann statt dem Interrupt 10 Blabla das "ISR20h" ausgegeben werden. Das "Hallo Welt" und "Bsy bla" kann schon da bleiben. Das "ISR20h" fehlt jetzt eben noch. Vermutlich liegt's daran, dass ich im sect2.asm file immer noch ein Durcheinander habe und er nicht zur Ausgabe kommt?!
Code:
[BITS 16]
start:

    mov ax,0xB800
    mov es,ax
    
    mov AH, 02h
    mov BH,0
    int 0x10    

    mov AH,13h
    
    mov AL,1
    mov BH,0
    mov BL,0x1F
    mov CX,bsy1len
    mov ESI, 0x0500
    mov ES, ESI
    mov BP,bsy1msg
    
    int 0x10
    
   [COLOR=royalblue][B] int 20h[/B]
endloop:
    jmp endloop

my_isr:
    pusha
    push gs
    push fs
    push es
    push ds

    mov byte [es:0x00], 'I'
    mov byte [es:0x01], 00011111b
    mov byte [es:0x02], 'S'
    mov byte [es:0x03], 00011111b
    mov byte [es:0x04], 'R'
    mov byte [es:0x05], 00011111b
    mov byte [es:0x06], 'H'
    mov byte [es:0x07], 00011111b
    mov byte [es:0x08], '2'
    mov byte [es:0x09], 00011111b
    mov byte [es:0x0A], '0'
    mov byte [es:0x0B], 00011111b
    mov byte [es:0x0C], 'h'
    mov byte [es:0x0D], 00011111b

    pop ds
    pop es
    pop fs
    pop gs
    popa

    iret
    
    xor ax, ax
    mov es, ax

    mov dx, my_isr
    mov [es:20h * 4], dx

    mov ax, cs
    
    mov [es:20h * 4 + 2], ax
    
    jmp endloop
    
bsy1msg     db     13,10,"BSY1 via INT 10"
bsy1len     equ     $ - bsy1msg
Muss ich nicht, wie in C, irgendwie nach int 20h auf die "Funktion" my_isr verweisen? Wenn er's der Reihe nach abarbeitet, würde er ja sonst in der Endlosschleife landen, bevor er die Funktion sieht, oder läuft das bei Assembler anders?

Hätte ja testweise probiert:
Code:
jmp my_isr
Aber dann hängt er an die Ausgabe in "MiniOS" nur ein "Operating System not found" an ...
 
Zuletzt bearbeitet:
AW: [ASSEMBLER] Interrupt in Interrupt Tabelle einfügen

Mit dem Ausdruck int 20h rufst du deine ISR doch auf. int macht einen sog. Interrupt-Call und ruft die zur Nummer gehörende Funktion auf, da musst du nichts mit call oder jmp machen.

Dann hast du in deinem Code noch das Problem, dass du deine ISR zu spät registrierst, ich bin mir nicht mal sicher, ob dieser Code überhaupt ausgeführt wird. Du musst die Routine registrieren, bevor du den int 20h call machst, sonst klappt das natürlich nicht!

Code:
; Deine "main"
start:
    ; ...

    ; Register sichern (du hast ES mit einem anderen Wert initialisiert, den wollen wir nicht überschreiben)
    push ax
    push es

    ; ISR in IVT registrieren
    xor ax, ax
    mov es, ax

    mov dx, my_isr
    mov [es:20h * 4], dx
    mov ax, cs
    mov [es:20h * 4 + 2], ax

    ; register wiederherstellen
    pop es
    pop ax

    ; ISR aufrufen
    int 20h

    ; ...

endloop:
    jmp endloop



; Deine ISR
my_isr:
    ; ISR Code hierhin
    ; ...

    iret

Optional könnte man noch die alte ISR an 20h sichern, damit man die später wiederherstellen kann. War jetzt aber nicht gefordert, soweit ich das gesehen habe.
 
AW: [ASSEMBLER] Interrupt in Interrupt Tabelle einfügen

Mit folgendem Code erreiche ich aber nur (unabsichtlich), dass in der Ausgabe das "Hallo BSY" wegfällt, das aber dableiben soll:
Code:
[BITS 16]
start:

    mov ax,0xB800
    mov es,ax
    
    mov AH, 02h
    mov BH,0
    
    int 0x10    

    mov AH,13h
    
    mov AL,1
    mov BH,0
    mov BL,0x1F
    mov CX,bsy1len
    mov ESI, 0x0500
    mov ES, ESI
    mov BP,bsy1msg
    
    int 0x10
    
    pusha
    push gs
    push fs
    push es
    push ds
    
    xor ax, ax
    mov es, ax
    
    mov dx, my_isr
    mov [es:20h * 4], dx
    mov ax, cs    
    mov [es:20h * 4 + 2], ax
    
    pop ds
    pop es
    pop fs
    pop gs
    popa
    
    int 20h

endloop:
    jmp endloop

my_isr:
    mov byte [es:0x00], 'I'
    mov byte [es:0x01], 00011111b
    mov byte [es:0x02], 'S'
    mov byte [es:0x03], 00011111b
    mov byte [es:0x04], 'R'
    mov byte [es:0x05], 00011111b
    mov byte [es:0x06], 'H'
    mov byte [es:0x07], 00011111b
    mov byte [es:0x08], '2'
    mov byte [es:0x09], 00011111b
    mov byte [es:0x0A], '0'
    mov byte [es:0x0B], 00011111b
    mov byte [es:0x0C], 'h'
    mov byte [es:0x0D], 00011111b

    iret
    
bsy1msg     db     13,10,"BSY1 via INT 10"
bsy1len     equ     $ - bsy1msg
Wahrscheinlich überschreiben wir den Inhalt eines Registers, in dem das "Hallo BSY" gespeichert ist?! Von "ISRH20h" sehe ich aber weiterhin nichts ...

Kann es sein, dass ich die Ausgabe dafür auch so wie bsy1msg und bsy1len machen müsste, oder liegt der Fehler immer noch in der start Funktion? Nur push/pop ax und es, so wie in deinem Code oben, ist jedenfalls zuwenig. Da kommt eine komplett sinnlose Ausgabe mit Sonderzeichen. Wir brauchen offenbar schon alle Register, die du in einem deiner Postings auf der ersten Seite in den Code getan hast. So, wie eben jetzt bei mir hier. Aber irgendwas hat's wohl noch ...
 
Zuletzt bearbeitet:
AW: [ASSEMBLER] Interrupt in Interrupt Tabelle einfügen

Der Teil hier
Code:
pusha
push gs
push fs
push es
push ds

pop ds
pop es
pop fs
pop gs
popa
muss in deine ISR, siehe eins meiner ersten Postings. Das hat beim Registrieren der ISR keinen Sinn. Ich habe in meinem letzen Posting nur Code weggelassen, weil ich nicht so viel schreiben wollte, der muss aber dahin.

Die Ausgabe könntest du mal mit der anderen Variante probieren, da ich mir auch nicht sicher bin, ob die Speicherbereiche noch stimmen. Wenn du ES zu Beginn (bei start) mit der (Segment)Adresse des Videospeichers initialisierst, darf die natürlich nicht verloren gehen, der Registerinhalt muss also beim Registrieren der ISR gesichert werden (siehe mein letzes Posting). Außerdem kann es sein, dass wenn du bei Offset 0 im Videospeicher anfängst zu schreiben, er den bereits vorhanden Inhalt einfach überschreibt.
 
AW: [ASSEMBLER] Interrupt in Interrupt Tabelle einfügen

Capture.JPG

^^ Hat wieder nichts geändert. Ich glaube mittlerweile wirklich, dass es an der Ausgabe selbst scheitert ...

Stellt sich nur die Frage: Wie genau umschreiben? Wenn ich die ganzen mov byte Zeilen in der ISR lösche, fällt ja diese komplett weg?! Ohne Ausgabe-Code bringt mir ja auch das push/pop nichts?! Und das kann's ja auch nicht sein. Die ISR muss auf jeden Fall dableiben.

Das mit dem Videospeicher ist ja das mit [es:offset]?! Ok, da muss ich mir halt dann noch überlegen, ab welchem Offset die vorigen Ausgaben zu Ende sind und dann diesen Offset+1 als Startoffset für unser "ISRH20h" nehmen. Aber vorher will ich das zumindest mal irgendwo ausgegeben haben.
 
Zuletzt bearbeitet:
AW: [ASSEMBLER] Interrupt in Interrupt Tabelle einfügen

Das hier ist ein (zumindest bei mir) funktionierender Code für das setzen und Aufrufen der ISR.
Code:
[BITS 16]

ORG 0x7C00

start:
    xor ax, ax
    ; IVT beginnt bei 0. Das ist wichtig, wenn du ES mit der Videospeicher-Adresse initialisierst.
    ; Diese dann vorher mit push es sichern und nach dem setzen der ISR mittels pop es wiederherstellen.
    mov es, ax
    
    ; ISR setzen
    ; Interrupts aus
    cli
    ; int Nummer 20h wollen wir bearbeiten
    mov bx, 0x20
    ; Adresse x 4 da 4 Byte pro IVT Eintrag
    shl bx, 2
    ; Offsetadresse der ISR in IVT setzen
    mov [es:bx], word my_isr
    ; Segmentadresse der ISR in IVT setzen
    mov [es:bx + 2], ds
    ; Interrupts an
    sti
    
    ; ISR aufrufen
    int 0x20
    
endloop:
    jmp endloop


; INT 20h handler
my_isr:
    ; Register sichern
    pusha
    push gs
    push fs
    push es
    push ds
    
    ; Ausgabe
    mov ax, 0xB800
    mov es, ax
    
    mov byte [es:00], 'I'
    mov byte [es:01], 0x1F
    mov byte [es:02], 'S'
    mov byte [es:03], 0x1F  
    mov byte [es:04], 'R'
    mov byte [es:05], 0x1F
    mov byte [es:06], '2'
    mov byte [es:07], 0x1F    
    mov byte [es:08], '0'
    mov byte [es:09], 0x1F
    mov byte [es:10], 'h'
    mov byte [es:11], 0x1F
    
    ; Register wiederherstellen
    pop ds
    pop es
    pop fs
    pop gs
    popa
    
    ; ISR verlassen
    iret
    
; Magic Bytes schreiben
times 510 - ($ - $$) db 0
dw 0xAA55
Wenn du das mit nasm -f bin -o isr.img isr.asm übersetzt, kannst du bei VMware direkt die isr.img als Boot-Floppy verwenden.

Anhang anzeigen 608670

Ich habe versucht, deinen Code da drum zu basteln, aber schon ohne ISR bekomme ich keine Ausgabe, sondern nur einen blauen Streifen. Also habe ich es weggelassen ;)
 
AW: [ASSEMBLER] Interrupt in Interrupt Tabelle einfügen

Assemblieren kann ich's noch, aber wie genau boote ich dann MiniOS vom img? Es wird lokal nicht gespeichert, also kann ich nicht einfach in den VMWare Player Settings das img auswählen. Ich hätte noch probiert, das img auf die Diskette zu schreiben (./write sect2 --> bei mir heißt es sect2.img), aber da kommt nur "No such file or directory" ...

Wir haben zum Assemblieren übrigens diese komplett sinnlose Anleitung bekommen:

Capture.JPG

^^ Aber mit dem nasm Befehl hier geht gar nichts (ja, habe natürlich auf sect2.asm geändert). Nur mit deinem konnte ich es assemblieren.
 
AW: [ASSEMBLER] Interrupt in Interrupt Tabelle einfügen

Ah ihr habt ne fertige VM... okay. Also ich habe mir in VirtualBox eine simple DOS VM angelegt, ohne Festplatte/CD, nur mit Floppy. Dann gebe ich in den Einstellungen die img Datei für das virtuelle Floppy an und dann bootet der davon. Deswegen benötige ich in meinem Code auch diese Magic Byte Klamotte. Bei deinem write.c wird das manuell gesetzt (bootsector[510]...). Du müsstest den Code eigentlich in eine Datei packen können, die du dann als sect2 verwendest. Dann musst du aber meinen Magic Byte Code wieder rauswerfen, den brauchst du dann nicht.

Den Teil hier brauchst du auf jeden Fall.
Code:
    ; das muss in deine "Hauptroutine", die vom Bootloader aufgerufen wird (in deine vorhanden sect2?)
    xor ax, ax
    ; IVT beginnt bei 0. Das ist wichtig, wenn du ES mit der Videospeicher-Adresse initialisierst.
    ; Diese dann vorher mit push es sichern und nach dem setzen der ISR mittels pop es wiederherstellen.
    mov es, ax
    
    ; ISR setzen
    ; Interrupts aus
    cli
    ; int Nummer 20h wollen wir bearbeiten
    mov bx, 0x20
    ; Adresse x 4 da 4 Byte pro IVT Eintrag
    shl bx, 2
    ; Offsetadresse der ISR in IVT setzen
    mov [es:bx], word my_isr
    ; Segmentadresse der ISR in IVT setzen
    mov [es:bx + 2], ds
    ; Interrupts an
    sti
    
    ; ISR aufrufen
    int 0x20
    
endloop:
    jmp endloop


; INT 20h handler
my_isr:
    ; Register sichern
    pusha
    push gs
    push fs
    push es
    push ds
    
    ; Ausgabe
    mov ax, 0xB800
    mov es, ax
    
    mov byte [es:00], 'I'
    mov byte [es:01], 0x1F
    mov byte [es:02], 'S'
    mov byte [es:03], 0x1F  
    mov byte [es:04], 'R'
    mov byte [es:05], 0x1F
    mov byte [es:06], '2'
    mov byte [es:07], 0x1F    
    mov byte [es:08], '0'
    mov byte [es:09], 0x1F
    mov byte [es:10], 'h'
    mov byte [es:11], 0x1F
    
    ; Register wiederherstellen
    pop ds
    pop es
    pop fs
    pop gs
    popa
    
    ; ISR verlassen
    iret
 
AW: [ASSEMBLER] Interrupt in Interrupt Tabelle einfügen

Mit diesem Code bekomme ich genau "Hallo Welt" ausgegeben, weil das wahrscheinlich in irgendwelchen Registern gespeichert ist, die wir aufrufen, aber sonst nichts. Ich bin am Ende mit meinem Latein ...

sect2.asm
Code:
[BITS 16]

org 0x7C00

start:

    xor ax, ax
    ; IVT beginnt bei 0. Das ist wichtig, wenn du ES mit der Videospeicher-Adresse initialisierst.
    ; Diese dann vorher mit push es sichern und nach dem setzen der ISR mittels pop es wiederherstellen.
    mov es, ax
    
    ; ISR setzen
    ; Interrupts aus
    cli
    ; int Nummer 20h wollen wir bearbeiten
    mov bx, 0x20
    ; Adresse x 4 da 4 Byte pro IVT Eintrag
    shl bx, 2
    ; Offsetadresse der ISR in IVT setzen
    mov [es:bx], word my_isr
    ; Segmentadresse der ISR in IVT setzen
    mov [es:bx + 2], ds
    ; Interrupts an
    sti
    
    ; ISR aufrufen
    int 0x20
    
endloop:
    jmp endloop


; INT 20h handler
my_isr:
    ; Register sichern
    pusha
    push gs
    push fs
    push es
    push ds
    
    ; Ausgabe
    mov ax, 0xB800
    mov es, ax
    
    mov byte [es:00], 'I'
    mov byte [es:01], 0x1F
    mov byte [es:02], 'S'
    mov byte [es:03], 0x1F  
    mov byte [es:04], 'R'
    mov byte [es:05], 0x1F
    mov byte [es:06], '2'
    mov byte [es:07], 0x1F    
    mov byte [es:08], '0'
    mov byte [es:09], 0x1F
    mov byte [es:10], 'h'
    mov byte [es:11], 0x1F
    
    ; Register wiederherstellen
    pop ds
    pop es
    pop fs
    pop gs
    popa
    
    ; ISR verlassen
    iret
Ja, wir haben 2 fertige virtuelle Maschinen:
1. BSY1UE32 --> Entwicklungsumgebung
2. MiniOS --> Testumgebung (startet von der virtuellen Diskette, die in BSY1UE32 beschrieben wird)

Zum Beschreiben der Diskette werden immer die files boot.asm, Makefile, sect2.asm und write.c und der Befehl "make" verwendet.

Hier noch einmal der Inhalt:
boot.asm
Code:
[BITS 16]
org 0x7c00

start:
    mov ax,0xB800
    mov es,ax

    mov byte [es:0x00], 'H' 
    mov byte [es:0x01], 00011111b

    mov byte [es:0x02], 'a'
    mov byte [es:0x03], 00011111b

    mov byte [es:0x04], 'l'
    mov byte [es:0x05], 00011111b

    mov byte [es:0x06], 'l'
    mov byte [es:0x07], 00011111b

    mov byte [es:0x08], 'o'
    mov byte [es:0x09], 00011111b

    mov byte [es:0x0A], ' '
    mov byte [es:0x0B], 00011111b

    mov byte [es:0x0C], 'W'
    mov byte [es:0x0D], 00011111b

    mov byte [es:0x0E], 'e'
    mov byte [es:0x0F], 00011111b

    mov byte [es:0x10], 'l'
    mov byte [es:0x11], 00011111b

    mov byte [es:0x12], 't'
    mov byte [es:0x13], 00011111b

    mov ax,sect2dest
    mov es,ax
    mov ah,0x02
    mov al,1
    mov ch,0
    mov cl,2
    mov dh,0
    mov dl,0
    mov bx,0

    int 0x13

    sect2dest equ 0x0500

    jmp sect2dest
Makefile.asm
Code:
all : boot write disk

boot    : boot.asm sect2.asm
        nasm -o boot boot.asm
        nasm -o sect2 sect2.asm

disk    : write
        ./write boot sect2

write   : write.c
        cc write.c -o write

clean   :
        rm boot sect2 write
write.c
Code:
#include <unistd.h>
#include <fcntl.h>
#include <stdio.h>

int main(int argc, char* argv[]) {
        char bootsector[512];
        int floppy, bootcode;
        if (argc < 2) {
                printf("Syntax: %s codefile\n",argv[0]);
                return 0;
        }
        bootcode = open(argv[1], O_RDONLY);
        if( bootcode != -1 ) {
                read(bootcode, bootsector, 510);
                close(bootcode);
                bootsector[510] = 0x55;
                bootsector[511] = 0xaa;
                floppy = open("/dev/fd0", O_RDWR);
                if ( floppy != -1) {
                        lseek(floppy, 0, SEEK_SET);
                        write(floppy, bootsector, 512);
                        printf("%s auf FDD geschrieben\n", argv[1]);
                        close(floppy);
                } else {
                        printf("Fehler beim Schreiben\n");
                }
        } else {
                printf("Fehler beim Lesen\n");
        }
        
        bootcode = open(argv[2], O_RDONLY);
        if( bootcode != -1 ) {
                read(bootcode, bootsector, 512);
                close(bootcode);
                floppy = open("/dev/fd0", O_RDWR);
                if ( floppy != -1) {
                        lseek(floppy, 512, SEEK_SET);
                        write(floppy, bootsector, 512);
                        printf("%s auf FDD geschrieben\n", argv[2]);
                        close(floppy);
                } else {
                        printf("Fehler beim Schreiben\n");
                }
        } else {
                printf("Fehler beim Lesen\n");
        }
}
^^ Aus der boot.asm kommt das "Hallo Welt", das ist klar. Aber wo das "ISR20h" bei mir bleibt? K.A. ...
 
Zuletzt bearbeitet:
AW: [ASSEMBLER] Interrupt in Interrupt Tabelle einfügen

So, ich habe mir jetzt mal einen Gesamtüberblick verschafft. Meine Vermutung ist momentan, dass es am Laden des 2. Sektors scheitert. Ich versuche mal, ob ich da was auf die Schnelle zusammengebastelt bekomme...
 
AW: [ASSEMBLER] Interrupt in Interrupt Tabelle einfügen

Naja, bei Aufgabe b und c musste ich ja auch schon 2 Sektoren laden und da hat das mit dem exakt selben write.c file funktioniert. Sieht man ja auf den Bildern in den vorderen Thread-Seiten, dass da mehrer Sachen ausgegeben werden --> "Hallo Welt", "Hallo BSY", "Interrupt 10 blabla". Das steht ja nicht alles im selben Sektor. Wieso es jetzt bei Aufgabe d plötzlich nicht mehr klappt, verstehe ich nicht. Der müsste ja nur das "Interrupt 10 bla" mit "ISR20h" überschreiben (siehe erstes Bild hier). Das "Hallo Welt" aus boot.asm kann ruhig dableiben und das "Hallo BSY" würde auch nichts machen ...
 
AW: [ASSEMBLER] Interrupt in Interrupt Tabelle einfügen

Der Lade-Code funktioniert doch, der hängt bei der ISR. Den Grund dafür habe ich aber noch nicht gefunden...
 
AW: [ASSEMBLER] Interrupt in Interrupt Tabelle einfügen

Na geht doch :ugly:
Ich hatte beim sect2 Code mittels ORG meine Basisadresse verbastelt, deswegen hat der irgendwie die falsche ISR aufgerufen bzw. ist irgendwo im Speicher gelandet.

boot.asm
Code:
[BITS 16]
[ORG 0x7C00]

jmp 0x0:start

start:  
    ; Zweiten Sektor lesen
    mov ax, sect2dest    ; Segmentadresse
    mov es, ax
    xor bx, bx
    mov ah, 0x02        ; Sektor lesen
    mov al, 0x01        ; 1 Sektor lesen
    mov ch, 0x00        ; Spur 0
    mov cl, 0x02        ; Sektor 2
    mov dh, 0x00        ; Kopf 0
    mov dl, 0x00        ; Laufwerk 0
    int 0x13
    
    ; Umgebung für Sektor 2 anpassen
    mov ax, sect2dest
    mov es, ax
    mov ds, ax
    
    jmp sect2dest:0x0    ; Programm aus Sektor 2 ausführen
    
; Zieladresse
sect2dest equ 0x1000

; Magic Bytes
times 510 - ($ - $$) db 0
dw 0xAA55
sect2.asm
Code:
[BITS 16]

sect2:
    push es            ; ES sichern
    
    ; ISR setzen
    xor ax, ax                    ; AX = 0
    mov es, ax                    ; ES = 0 (für IVT)
    mov bx, 0x20                ; int 20h
    shl bx, 2                    ; Adresse x 4, da 4 Byte pro IVT Eintrag
    mov ax, isr_20h                ; Adresse der ISR in AX speichern
    cli                            ; Interrupts aus
    mov [es:bx], ax                ; Adresse der ISR in IVT setzen
    mov [es:bx + 2], cs            ; Segment der ISR in IVT setzen
    sti                            ; Interrupts an
    
    pop es        ; ES wiederherstellen
    
    int 0x20    ; ISR aufrufen
    
halt:
    cli            ; Interrupts aus
    hlt            ; Halt
    jmp halt    ; just in case


; INT 20h handler
isr_20h:
    ; Register sichern
    push ax
    push es
    
    ; Ausgabe
    mov ax, 0xB800
    mov es, ax
    
    mov byte [es:00], 'I'
    mov byte [es:01], 0x1F
    mov byte [es:02], 'S'
    mov byte [es:03], 0x1F
    mov byte [es:04], 'R'
    mov byte [es:05], 0x1F
    mov byte [es:06], '2'
    mov byte [es:07], 0x1F
    mov byte [es:08], '0'
    mov byte [es:09], 0x1F
    mov byte [es:10], 'h'
    mov byte [es:11], 0x1F
    
    ; Register wiederherstellen
    pop es
    pop ax
    
    ; ISR verlassen
    iret

; Rest des Sektors füllen (auf 512 Byte gesamt)
times 512 - ($ - $$) db 0
build.bat (im Prinzip was deine write.c macht; erzeugt das Floppy Image als minios.img)
Code:
@echo off

echo Erzeuge boot...
nasm -f bin -o boot boot.asm

echo Erzeuge sect2...
nasm -f bin -o sect2 sect2.asm

echo Erzeuge Image-Datei...
copy /B /Y boot + sect2 minios.img
Damit funktioniert es nun bei mir. Die build.bat brauchst du vermutlich nicht, die habe ich nur so der Vollständigkeit halber dazu gepackt.
 
Zuletzt bearbeitet:
AW: [ASSEMBLER] Interrupt in Interrupt Tabelle einfügen

Huch, wenn ich deine obige boot.asm und sect2.asm verwende, schließt sich das MiniOS Fenster gleich nach dem Start. Ich sehe die Ausgabe gar nicht ...

Ich versuche gerade zu verstehen, was an deiner jetzigen boot.asm so viel anders ist, als an meiner. Zeigst du nicht ziemlich wild im Speicher herum? Ich dachte, ich brauche nie mehr, als die 0xB800 Adresse für den Videospeicher und die 0x0500 für den Sektor 2?!

[EDIT]
Habe noch ein Bisschen herumgetestet: Mit meiner boot.asm kommt nur "Hallo Welt", ergo wird da wohl nie auf den Sektor 2 verwiesen?! Bei deiner boot.asm schließt sich bei mir sofort das MiniOS Fenster bevor ich überhaupt eine Ausgabe sehe. K.A., was da falsch ist.

Ideal wäre es natürlich wenn wir einfach nur meine boot.asm um das nötige Zeug ergänzen könnten, anstatt einer komplett neuen zu verwenden, weil ja das "Hallo Welt" nicht verschwinden soll. Ich versuche jetzt mal, das "nötige", soweit ich es erkenne, aus deiner boot.asm zu nehmen und in meine reinzubasteln ...
 
Zuletzt bearbeitet:
AW: [ASSEMBLER] Interrupt in Interrupt Tabelle einfügen

Dass ich 0x1000 statt 0x0500 geschrieben habe, hat eigentlich keinen speziellen Grund, ist vom Rumprobieren übrig geblieben ^^
Abgesehen davon müsste die boot.asm eigentlich ziemlich gleich geblieben sein, zumindest habe ich daran nicht viel gemacht (außer Kommentare + Reihenfolge geändert vielleicht).
Das jmp sieht noch anders aus, macht aber das gleiche wie bei dir. Ich wollte nur sichergehen, dass ich auch zur richtigen Adresse springe, also zu Segment 0x1000, Offset 0x0. Schließlich habe ich da ja den 2. Sektor hingeladen. Zu dem jmp sect2dest:0x0 - siehe meinen nächsten Post. Hätte mir eigentlich hier schon auffallen müssen ^^

An der sect2 habe ich mehr geändert. Kannst du vielleicht noch mal den Code posten, der jetzt nicht funktioniert? Ich habe zwischenzeitlich mal das Phänomen gehabt, dass die VM nach der Ausgabe direkt einen Neustart gemacht hat. Allerdings war da noch die falsche ISR beteiligt.

Edit: Hast du meine boot.asm mit deiner sect2.asm kombiniert? Du musst bei der sect2.asm das ORG entfernen, sonst funktioniert die ISR auf jeden Fall nicht. Das war zumindest bei mir der Fehler. Und man braucht bei der ISR wohl auch nur die Register sichern, die man tatsächlich nutzt (siehe meine sect2.asm).
 
Zuletzt bearbeitet:
AW: [ASSEMBLER] Interrupt in Interrupt Tabelle einfügen

Ausgabe: "Hallo Welt" (aus boot.asm) ...

boot.asm
Code:
[BITS 16]
org 0x7c00

start:
    mov ax,0xB800
    mov es,ax
    
    mov byte [es:0x00], 'H' 
    mov byte [es:0x01], 00011111b
    mov byte [es:0x02], 'a'
    mov byte [es:0x03], 00011111b
    mov byte [es:0x04], 'l'
    mov byte [es:0x05], 00011111b
    mov byte [es:0x06], 'l'
    mov byte [es:0x07], 00011111b
    mov byte [es:0x08], 'o'
    mov byte [es:0x09], 00011111b
    mov byte [es:0x0A], ' '
    mov byte [es:0x0B], 00011111b
    mov byte [es:0x0C], 'W'
    mov byte [es:0x0D], 00011111b
    mov byte [es:0x0E], 'e'
    mov byte [es:0x0F], 00011111b
    mov byte [es:0x10], 'l'
    mov byte [es:0x11], 00011111b
    mov byte [es:0x12], 't'
    mov byte [es:0x13], 00011111b

    mov ax,sect2dest
    mov es,ax
    mov ah,0x02
    mov al,1
    mov ch,0
    mov cl,2
    mov dh,0
    mov dl,0
    mov bx,0

    int 0x13

    sect2dest equ 0x0500

    jmp sect2dest
sect2.asm
Code:
[BITS 16]

sect2:
    push es         
    
    xor ax, ax               
    mov es, ax                
    mov bx, 0x20             
    shl bx, 2                 
    mov ax, isr_20h              
    cli                     
    mov [es:bx], ax             
    mov [es:bx + 2], cs       
    sti                          
    
    pop es    
    
    int 0x20   
    
halt:
    cli          
    hlt        
    jmp halt  

isr_20h:
    push ax
    push es
    
    mov ax, 0xB800
    mov es, ax
    
    mov byte [es:00], 'I'
    mov byte [es:01], 0x1F
    mov byte [es:02], 'S'
    mov byte [es:03], 0x1F
    mov byte [es:04], 'R'
    mov byte [es:05], 0x1F
    mov byte [es:06], '2'
    mov byte [es:07], 0x1F
    mov byte [es:08], '0'
    mov byte [es:09], 0x1F
    mov byte [es:10], 'h'
    mov byte [es:11], 0x1F
    
    pop es
    pop ax
    
    iret

times 512 - ($ - $$) db 0
----------------------

Ausgabe: nicht sichtbar. Fenster der virtuellen Maschine "MiniOS" schließt sich sofort nach Start ...

boot.asm
Code:
[BITS 16]
[ORG 0x7C00]

jmp 0x0:start

start:  
    mov ax, sect2dest   
    mov es, ax
    xor bx, bx
    mov ah, 0x02      
    mov al, 0x01   
    mov ch, 0x00       
    mov cl, 0x02    
    mov dh, 0x00     
    mov dl, 0x00        
    int 0x13
    
    mov ax, sect2dest
    mov es, ax
    mov ds, ax
    
    jmp sect2dest:0x0    
    
sect2dest equ 0x1000

times 510 - ($ - $$) db 0
dw 0xAA55
sect2.asm
Code:
[BITS 16]

sect2:
    push es         
    
    xor ax, ax               
    mov es, ax                
    mov bx, 0x20             
    shl bx, 2                 
    mov ax, isr_20h              
    cli                     
    mov [es:bx], ax             
    mov [es:bx + 2], cs       
    sti                          
    
    pop es    
    
    int 0x20   
    
halt:
    cli          
    hlt        
    jmp halt  

isr_20h:
    push ax
    push es
    
    mov ax, 0xB800
    mov es, ax
    
    mov byte [es:00], 'I'
    mov byte [es:01], 0x1F
    mov byte [es:02], 'S'
    mov byte [es:03], 0x1F
    mov byte [es:04], 'R'
    mov byte [es:05], 0x1F
    mov byte [es:06], '2'
    mov byte [es:07], 0x1F
    mov byte [es:08], '0'
    mov byte [es:09], 0x1F
    mov byte [es:10], 'h'
    mov byte [es:11], 0x1F
    
    pop es
    pop ax
    
    iret

times 512 - ($ - $$) db 0
 
AW: [ASSEMBLER] Interrupt in Interrupt Tabelle einfügen

Also dein geposteter Code funktionierte bei mir auch nicht, der blieb bei mir nach Hallo Welt hängen. Den Fehler habe ich aber gefunden, dein jmp in den geladenen Sektor funktionierte nicht (Segment-Offset-Adressierung sei dank :ugly:). Das habe ich auch leider irgendwie übersehen, sonst hätte ich schon früher was gesagt (mea culpa...). Mit
Code:
jmp sect2dest ; sect2dest = 0x0500
springst du an Adresse 0x0500, wir haben den 2. Sektor aber an Adresse 0x0500:0x0 geladen, d. h. 0x0500 * 0x10 + 0x0 = 0x5000 effektiv. Die Speicheradresse berechnet sich bei Segment-Offset-Adressierung nämlich zu Segment * 16 + Offset (16 dezimal = 10 Hex).

Wenn ich in deinem Code das jmp also durch
Code:
jmp sect2dest:0x0
ersetze, wird auch der Code aus sect2 aufgerufen.

Zum Fehler 2: Kannst du mal bitte das int 0x20 in sect2 auskommentieren? Damit können wir feststellen, ob der Fehler in der ISR selbst liegt. Wenn das nicht funktioniert, bitte mal folgendes probieren
Code:
halt:
    ;cli
    ;hlt
    jmp halt
Das ist die Endlosschleife von vorher (die 100% CPU Last erzeugt). Mit dem hlt Befehl wird die CPU "angehalten", bis ein Interrupt auftritt (was ich hier aber mit cli teilweise unterdrückt habe, NMIs können aber immer noch auftreten -> deswegen noch das jmp halt).
 
AW: [ASSEMBLER] Interrupt in Interrupt Tabelle einfügen

Mit folgenden Codes habe ich jetzt diese Ausgabe bekommen:

Capture.JPG

^^ :daumen: Wenn wir's jetzt nur noch schaffen würden, die Startausgabeadresse von "ISR20h" so zu ändern, dass er das unter "Hallo Welt" schreibt, anstatt dieses zu überschreiben, wäre ich komplett glücklich ...

boot.asm
Code:
[BITS 16]
org 0x7c00

start:
    mov ax,0xB800
    mov es,ax

    mov byte [es:0x00], 'H' 
    mov byte [es:0x01], 00011111b
    mov byte [es:0x02], 'a'
    mov byte [es:0x03], 00011111b
    mov byte [es:0x04], 'l'
    mov byte [es:0x05], 00011111b
    mov byte [es:0x06], 'l'
    mov byte [es:0x07], 00011111b
    mov byte [es:0x08], 'o'
    mov byte [es:0x09], 00011111b
    mov byte [es:0x0A], ' '
    mov byte [es:0x0B], 00011111b
    mov byte [es:0x0C], 'W'
    mov byte [es:0x0D], 00011111b
    mov byte [es:0x0E], 'e'
    mov byte [es:0x0F], 00011111b
    mov byte [es:0x10], 'l'
    mov byte [es:0x11], 00011111b
    mov byte [es:0x12], 't'
    mov byte [es:0x13], 00011111b

    mov ax,sect2dest
    mov es,ax
    mov ah,0x02
    mov al,1
    mov ch,0
    mov cl,2
    mov dh,0
    mov dl,0
    mov bx,0

    int 0x13

    jmp sect2dest:0x0
    
    sect2dest equ 0x0500
sect2.asm
Code:
[BITS 16]

sect2:
    push es            
    
    xor ax, ax                    
    mov es, ax                    
    mov bx, 0x20                
    shl bx, 2                    
    mov ax, isr_20h               
    cli                            
    mov [es:bx], ax                
    mov [es:bx + 2], cs           
    sti                            
    
    pop es       
    
    int 0x20   
    
endloop:
    jmp endloop

isr_20h:
    push ax
    push es
    
    mov ax, 0xB800
    mov es, ax
    
    mov byte [es:00], 'I'
    mov byte [es:01], 0x1F
    mov byte [es:02], 'S'
    mov byte [es:03], 0x1F
    mov byte [es:04], 'R'
    mov byte [es:05], 0x1F
    mov byte [es:06], '2'
    mov byte [es:07], 0x1F
    mov byte [es:08], '0'
    mov byte [es:09], 0x1F
    mov byte [es:10], 'h'
    mov byte [es:11], 0x1F
    
    pop es
    pop ax
    
    iret
Das int 0x20 musste ich gar nicht auskommentieren, meine Endlosschleife konnte ich auch drinnen lassen und die time Zeile am Ende von sect2.asm, was auch immer die machen hätte sollen, brauche ich scheinbar auch nicht. :)

Vielen Dank schon mal soweit! Wie gesagt, würde ich nur noch gerne die Ausgabe ein Bisschen verändert haben, dass beides lesbar ist und dann hätte ich noch ein paar Verständnisfragen zum Code selbst.
Das mit der Ausgabe probiere ich eh gleich selber. Mal schauen, wie weit ich kommen ...
 
Zurück