Diskette Sektoren lesen und schreiben



  • Man braucht heute nur sehr selten Disketten. Die meisten PCs haben kein Disketten-Lw mehr. Man kann aber für etwa 10 Euro ein Disk-Lw mit USB Anschluss kaufen und das funktioniert wie ein normales Disketten-Lw.

    Wenn ich in einem 32-bit Windows mein altes mit TurboPascal programmiertes Programm laufen lasse, dann funktioniert es dort immer noch wie vor 20 Jahren unter DOS. Im 64-bit Windows kann man es nicht ausführen.

    Damals habe ich die Zugriffe über BIOS-Aufrufe gemacht, die ja offensichtlich auch heute in Win10-1903-32 immer noch funktionieren.

    Wie müsste man das heute programmieren ?

    Hier mal die Funktionen für die Disketten-Zugriffe

    { -------------------------------------------------------------------
      ---                Einen Sektor verifizieren                    ---
      ------------------------------------------------------------------- }
    Function VerifySektor(LaufwNr,SeiteNr,SpurNr,
                          SektorNr,AnzSekt:Byte):Word;
      Begin
        Regs.AH := $04;      { Sektor verifyzieren }
        Regs.DL := LaufwNr;  { 0 = Laufwerk A: }
        Regs.DH := SeiteNr;  { Seite 0 }
        Regs.CH := SpurNr;   { Spur    }
        Regs.CL := SektorNr; { Sektor  }
        Regs.AL := AnzSekt;  { Anzahl Sektoren = 1 }
        Intr($13,Regs);
        if ( ( (Regs.Flags and FCarry) = FCarry ) or (Regs.AH <> 0) )
          then  VerifySektor := Regs.AH
          else  VerifySektor := 0;
    
      End;       { Ende - Function VerifySektor }
    
    { -------------------------------------------------------------------
      ---                Einen Sektor lesen ( 512 Bytes )             ---
      ------------------------------------------------------------------- }
    Function ReadSektor(LaufwNr,SeiteNr,SpurNr,SektorNr:Byte):Word;
      Begin
        Regs.AH := $02;               { Sektor lesen }
        Regs.DL := LaufwNr;           { 0 = Laufwerk A: }
        Regs.DH := SeiteNr;           { Seite 0 }
        Regs.CH := SpurNr;            { Spur    }
        Regs.CL := SektorNr;          { Sektor  }
        Regs.AL := 1;                 { Anzahl Sektoren = 1 }
        Regs.ES := Seg(SektPuff[1]);  { ES:BX = Eingabe-Puffer }
        Regs.BX := Ofs(SektPuff[1]);
    
        Intr($13,Regs);
        if ( ( (Regs.Flags and FCarry) = FCarry ) or (Regs.AH <> 0) )
          then  ReadSektor := Regs.AH   { Fehlercode }
          else  ReadSektor := 0;        { ok. }
    
      End;       { Ende - Function ReadSektor }
    
    { -------------------------------------------------------------------
      ---              Einen Sektor ausgeben ( 512 Bytes )            ---
      ------------------------------------------------------------------- }
    Function WriteSektor(LaufwNr,SeiteNr,SpurNr,SektorNr:Byte):Word;
      Begin
        Regs.AH := $03;               { Sektor schreiben }
        Regs.DL := LaufwNr;           { 0 = Laufwerk A: }
        Regs.DH := SeiteNr;           { Seite 0 }
        Regs.CH := SpurNr;            { Spur    }
        Regs.CL := SektorNr;          { Sektor  }
        Regs.AL := 1;                 { Anzahl Sektoren = 1 }
        Regs.ES := Seg(SektPuff[1]);  { ES:BX = Ausgabe-Puffer }
        Regs.BX := Ofs(SektPuff[1]);
    
        Intr($13,Regs);
        if ( ( (Regs.Flags and FCarry) = FCarry ) or (Regs.AH <> 0) )
          then  WriteSektor := Regs.AH   { Fehlercode }
          else  WriteSektor := 0;        { ok. }
    
      End;       { Ende - Function WriteSektor }
    
    { -------------------------------------------------------------------
      ---                RESET auf Laufwerk 0=A, 1=B                  ---
      ------------------------------------------------------------------- }
    Function DiskReset(LaufwNr:Byte):Word;
      Begin
        Regs.AH := $00;      { Reset }
        Regs.DL := LaufwNr;  { 0 = Laufwerk A: }
        Intr($13,Regs);
        if ( ( (Regs.Flags and FCarry) = FCarry ) or (Regs.AH <> 0) )
          then  DiskReset := Regs.AH
          else  DiskReset := 0;
    
      End;       { Ende - Function DiskReset }
    


  • datei auf laufwerk a zum lesen bzw. schreiben öffnen und dann über einen ganz normalen dateizugriff. ich weiß jetzt grad nicht, wie man das mit c# macht.

    und windows 10 lässt dich ernsthaft noch mit interrupts und ports auf die hardware zugreifen?



  • Benötigst du wirklich eine ".NET"-Lösung?
    In der WinAPI gibt es die Funktion DeviceIoControl, s.a. Device Input and Output Control (IOCTL).

    Für Zugriffe aus dem .NET Framework heraus müßtest du PInvoke verwenden: DeviceIoControl (kernel32).



  • @Wade1234 sagte in Diskette Sektoren lesen und schreiben:

    datei auf laufwerk a zum lesen bzw. schreiben öffnen und dann über einen ganz normalen dateizugriff

    Damit bekomst du aber nicht den Bootsektor, oder direkt die FAT.

    und windows 10 lässt dich ernsthaft noch mit interrupts und ports auf die hardware zugreifen?

    Die Interrupts können auch von Windows abgefangen werden und Ports werden hier nicht benutzt.



  • ach so war das gemeint. also grundsätzlich kann man unter windows (als administrator!) soweit ich weiß auch mit createfile auf festplatten bzw. laufwerke an sich zugreifen. aber warum verwendet man dafür eine programmiersprache, die gar nicht dafür gedacht ist?



  • @Wade1234 Watt du nicht alles weisst wofür Dinge gedacht sind. Krass.



  • @hkdd Google mal die Stichworte

    Windows open block device
    DeviceIoControl
    IOCTL_DISK_VERIFY

    Evtl. auch interessant der Code des "floppy" Driver Samples, dort siehst du welche Funktionen/IOCTLs dieser implementiert: https://github.com/microsoft/Windows-driver-samples/blob/master/storage/sfloppy/src/floppy.c



  • @hustbaer sagte in Diskette Sektoren lesen und schreiben:

    @Wade1234 Watt du nicht alles weisst wofür Dinge gedacht sind. Krass.

    naja warum muss man dann umständlich die windows api benutzen um auf das laufwerk zuzugreifen? oder funktioniert das doch mit c#?



  • @Wade1234 C# hat mit PInvoke ein sehr mächtiges, einfaches, praktisches Feature um WinAPI Funktionen (bzw. generell native Funktionen) aufzurufen. Macht auf mich nicht greade den Eindruckt dass C# nicht dazu gedacht wäre das dann auch zu tun.

    Ob es das ideale Tool dafür ist ist wieder ne andere Frage. Das hängt dann aber auch wieder vom konkreten Fall ab. Wenn man z.B. 5 WinAPI Funktionen und 2-3 WinAPI Datenstrukturen braucht (für die man sich dann den passenden PInvoke Code suchen/schreiben muss), dafür aber 1000+ Zeilen Code schreibt wo man von anderen C# Features profitiert... wieso sollte man dann nicht C# nehmen?



  • ja sicherlich. aber warum sollte man rohdaten auf eine diskette schreiben, wenn es mit der erzeugung einer datei deutlich einfacher (eine kurze recherche im internet hat 3 zeilen ergeben) geht?

    und wenn man schon solche spielereien wie "bootsektor der diskette" betreiben will, dann doch vielleicht lieber die windows api oder noch besser unix mit C.


  • Mod

    @Wade1234 : Warum? Ein Blockdevice ist auch nur ein dateiartiges Objekt. Mit C# kann man doch hoffentlich genauso Dateien mit beliebigem Inhalt Lesen und Schreiben wie in jeder anderen Sprache auch? Bloß weil da spukige Wörter wie "Bootsektor" in der Beschreibung des logischen(!) Dateiinhaltes vorkommen, macht das doch keinen Unterschied für den technischen Zugriff.
    Ebenso für Zugriff auf die Betriebssystem-API. Bloß weil das Funktionen sind, die du nicht so oft benutzt, macht das auch nicht auf magische Weise einen Unterschied für die aufrufende Sprache. Ein Winapi-Call ist ein Winapi-Call, egal ob der IOCTL_DISK_VERIFY oder CreateWindow heißt.



  • Danke für Euere Antworten.
    Ich habe von meinen Disketten jeweils eine IMG-Datei mit Hilfe eines Programmes, das so etwas kann, gemacht. Da werden die 2880 Sektoren nacheinander gelesen und in eine Datei geschrieben. Die kann man dann mit diesem Commander ähnlich wie eine ZIP-Datei öffnen und auf die Dateien zugreifen. Bei Bedarf kann man diese IMG-Daten wieder auf eine Diskette zurück schreiben. Das ist gerade für bootfähige Disketten wichtig. Bei Disketten, die lediglich Dateien enthalten, wäre das nicht nötig.
    Wenn das mein Commander kann , aber auch andere Programme, wie HxD oder RawWriteWin.exe, dann müsste das doch auch mit einem eigenen Programm möglich sein.



  • @Th69 ,
    ich habe das Beispiel aus Deinem Link ausprobiert.
    https://docs.microsoft.com/de-de/windows/desktop/DevIO/calling-deviceiocontrol

    Darin gibt es gleich am Anfang die Anweisung

    #define wszDrive L"\\\\.\\PhysicalDrive0"
    

    Damit wird aber die erste Festplatte angesprochen.
    Was muß man stattdessen benutzen, um das Disketten-Laufwerk anzusprechen.
    In der Datenträgerverwaltung wird das Disketten-Laufwerk nicht gelistet, auch nicht von Diskpart bei LIST DISK



  • @SeppJ
    ja da hast du wohl recht. aber bei c# würde ich dann sowas wie "blockdevicestream" oder so erwarten und kein umständliches pinvoke auf die winapi. also meiner meinung nach ist c# ein werkzeug, um bequem desktopanwendungen zu entwickeln und nicht um an der hardware herumzuspielen.

    @hkdd
    ja mit deinem eigenen programm ist das grundsätzlich ja auch möglich. die mögliche vorgehensweise mit pinvoke und createfile wurde dir ja auch schon genannt. vielleicht hilft das noch: https://stackoverflow.com/questions/55175218/pinvoke-windowsapi-createfile-from-c-sharp

    ps: unter unix schreibst du übrigens einfach nur "cat /dev/irgendwas > backup.img" zum sichern und "cat backup.img > /dev/irgendwas" zum wiederaufspielen in die shell. 😃



  • @hkdd
    funktioniert das diskettenlaufwerk denn überhaupt bzw. wird es im arbeitsplatz (bzw. mittlerweile heißt das ja "dieser pc") angezeigt?



  • Ich habe es einfach mal probiert und es fuktioniert.
    Mit der Anweisung

    #define wszDrive L"\\\\.\\A:"
    

    wird tatsächlich das Disketten-Laufwerk A: angesprochen.
    Nun muss ich nur noch herausfinden, wie man der Reihe nach die Sektoren lesen und schreiben kann.

    Es sei angemerkt, dass das Programm in C++ codiert ist, nicht in C#. Das ist mir eigentlich egal, ich könnte es auch in Delphi schreiben, ich wollte nur wissen, wie man unter Windows 10 diese Aufgabe lösen kann.

    Nochmals Dank an @Th69 für den Hinweis.

    @Wade1234 ,
    ja, es funktioniert einwandfrei und die genannten Programme können IMG erstellen bzw. IMGs auf Disk schreiben. Ich kann auch die Dateien der Diskette lesen. Der Explorer zeigt Laufwerk A: an.
    Man kann von Diskette booten (wenn im Bios so eingestellt) usw.



  • @hkdd sagte in Diskette Sektoren lesen und schreiben:

    Nun muss ich nur noch herausfinden, wie man der reihe nach die Sektoren lesen und schreiben kann.

    Lesen und Schreiben geht einfach mit ReadFile und WriteFile. Die Zugriffe müssen dabei halt Sector-Aligned sein - also immer nur ganze Sektoren lesen/schreiben. DeviceIoControl brauchst du dann für Sachen wie "verify".



  • @Wade1234 sagte in Diskette Sektoren lesen und schreiben:

    also meiner meinung nach ist c# ein werkzeug, um bequem desktopanwendungen zu entwickeln und nicht um an der hardware herumzuspielen.

    Also jeder der Server-Anwendungen damit macht macht auch was falsch?



  • @hustbaer ,
    kommen da die Sektoren in der richtigen Reihenfolge ?
    Bei der BIOS-Programmierung musste man ja wissen, wie viele Sektoren pro Spur, wie viele Spuren,. und auch noch die Seite 0 und 1. Das war für 1,44 GB Disketten ein ganz bestimmtes Muster.
    Ich werde es probieren. Ich habe mir extra eine Diskette eingerichtet, auf der die Sektoren mit eindeutigem Inhalt beschrieben sind.



  • kommt auf den server an würde ich sagen. aber ich muss zugeben, dass ich da jetzt nicht so die ahnung von habe, weil ich bei sowas immer direkt mit dem betriebssystem geplaudert habe.


Log in to reply