Verständnisproblem mit dynamischem Speicher



  • Ishildur schrieb:

    @NabuoT

    (irgendwie scheint mein Name echt schwierig zu lesen zu sein - *gg)

    Ishildur schrieb:

    Wenn ich nun ein Code, Stack sowie mehrere Datensegmente habe, dann wird ja ein bestimmer des mir zur Verfügung stehenden Speichers zwischen 07c00h und 98000h für jene Segmente benutzt. Wenn ich nun also zur Laufzeit zusätzlichen Arbeitsspeicher benötige, woher kann ich denn nun wissen, welcher Teil zwischen 07c00h und 98000h noch benutzt werden darf? Der Stack bspw. startet ja AFAIK bei der höchsten Adresse und breitet sich anschliessend in die tieferen Adressen aus. Kann es also sein, dass der Stack bei 98000h anfängt? Dann könnte ich das ESP Register abfragen, um zu wissen, wo die obere Grenze liegt. Doch woher kann ich nun wissen, wo die Untere Grenze liegt?

    Ich gehe mal davon aus, dass du fuer einen PC programmierst?
    Wenn du ohne OS arbeitest, wird dein 512Byte Bootsektor vom BIOS nach 7C00h (wie diese phys. Adresse im RM sich auf Segment:Offset verteilt kann je nach BIOS verschieden sein!) geladen. Wenn du einen anderen Bootloader benutzt evtl. auch woanders hin - das musst du der Doku entnehmen.
    Am Anfang deines Codes ist im Grunde alles undefiniert. Das Einzige was sicher ist, sind die Funktionen des BIOS, und die Adresse deines Codes.
    Zuerst wirst du deinen Stack anlegen muessen - dessen Adresse ist am Anfang naemlich auch undefiniert. Praktischerweise wirst du den vielleicht erstmal zB. nach 7C00:0000 (ber erste gepushte Wert wird dann bei 7C00:FFFE landen) packen. Da du weisst, dass dein Code bei 07C00-07E00 liegt, hast du dann also 512 Byte Stack zur verfuegung - von 07E00-08000.
    Nun wirst du als naechstes wohl den Rest deines Codes nachladen wollen. Den packst du dann vielleicht nach 08000 bis (wie gross auch immer dein Code evtl. mit Datensegmenten wird) 18000. Wenn du dann in deinen nachgeladenen Code springst, kannst du deinen von BIOS zuerst geladenen Code ueberschreiben lassen und hast dann 1024Byte Stack. ... usw.
    Also wie gesagt: Haengt wirklich alles von dir ab, es gibt keine Vorgaben.

    Ishildur schrieb:

    x_oben = ESP

    Im RealMode wird allerdings nur SP zum adressieren benutzt.

    Bashar schrieb:

    Das Betriebssystem ist zwar letztendlich dafür zuständig, einem Prozess Speicher zur Verfügung zu stellen, aber nicht in der Granularität, die man z.B. für eine verkettete Liste benötigt.

    Naaaja, praktisch vielleicht nicht dazu gedacht, aber moeglich waere es (notfalls halt mit etwas Speicherverschnitt).
    Mal ganz davon ab, wie genau die Listenelemente aussehen, wie gross sie sind, bzw. ob es in diesem Szenario ueberhaupt Sinn macht, ein in Hochsprachen idR. doch eher abstrakt verwendetes Konstrukt wie eine verkettete Liste zu benutzen...

    Bashar schrieb:

    Wenn man so eine Bibliothek nicht zur Verfügung hat, wird man sich wohl selbst was über Allokationsalgorithmen anlesen müssen.

    Da stimme ich zu. Ohne OS macht das wohl erst recht Sinn. Dazu muesste sich eigentlich auch noch was in der OS-Dev-Ecke finden.
    Ansonsten sind neue gute Links natuerlich auch gern gesehen. :xmas1:



  • @Nobuo<whitespace>T :p
    Ok, das habe ich glaube ich kapiert! Nun nur noch 2 Dinge: Mir ist noch überhaupt nicht klar, wie ich in den anderen Code springen kann.
    Ich habe 2 Dateien: boot.bin sowie pong.bin. Diese habe ich mit MagicIso in ein Image gepackt und auf eine Diskette geschrieben.
    Nun weiss ich ja, dass das BIOS den Code aus boot.bin in die Adresse 07c00h kopiert ok! Aber doch bloss die 512 Bytes des ersten Sektors. Die restlichen Daten befinden sich doch noch auf der Diskette und nicht im Arbeitsspeicher?! Wie kann ich dann einfach in dahin springen?

    2. Ich habe da noch ein Problem: Es ladet nicht einmal dieser verflixte Bootloader! Dies ist mein code:

    ORG 7C00h
    
    start: mov ax,03h
           int 10h
    	   mov ah,0eh
    	   mov al,'S'
    	   int 10h 
           jmp $
    TIMES 510-($-$$) DB 0
    DW 0AA55h
    

    Aber es kommt immer folgender Fehler:

    Disk formatted with MagicISO 4.70 (c) 2001-04 MagicISO, Inc.
    Bootsector form C.H. Hochstätter

    No Systemdisk. Booting from harddisk

    Also ich bin schon sehr überrascht, wie es möglich ist, dass an dieser Stelle Text von MagicIso steht?! Das kann doch eigentlich nur bedeuten, dass MagicSchrott da seinen eigenen Bootloader reingehackt hat?! Ein sehr ähnliches Problem hatte ich min WinImage! Gibt es irgendeine Software, die einfach mal das tut, was sie soll?



  • Ich habe das fertige Image mit einem Hex-Editor analysiert! Dieses Scheiss MagicIso überschreib meinen Programmcode komplett! :p



  • Ishildur schrieb:

    Nun weiss ich ja, dass das BIOS den Code aus boot.bin in die Adresse 07c00h kopiert ok! Aber doch bloss die 512 Bytes des ersten Sektors. Die restlichen Daten befinden sich doch noch auf der Diskette und nicht im Arbeitsspeicher?! Wie kann ich dann einfach in dahin springen?

    Wie ich bereits schrieb, musst du den restlichen Code natuerlich zuerst von der Diskette laden, bevor du reinspringen kannst.
    Dazu bietet es sich an, die BIOS Funktionen des int 13h zu benutzen - weitere Infos in FAQ, Forensuche, Internetsuche ... gibt wirklich genug zu dem Thema - auch Beispielcodes.

    Ishildur schrieb:

    2. Ich habe da noch ein Problem: Es ladet nicht einmal dieser verflixte Bootloader! Dies ist mein code:[...]

    Dazu sei noch angemerkt, dass auch Interrupt-Aufrufe den Stack verwenden. Wenn du keinen eingerichtet hast, kann das uU. zum Crash fuehren. Daher sollte wirklich das Erste, was du in deinem Bootloader machst, das Einrichten des Stacks und der Segmentregister sein.

    Ishildur schrieb:

    Dieses Scheiss MagicIso überschreib meinen Programmcode komplett!

    Versuch's mal mit RawRite o.Ae.? Das sieht ueberhaupt so aus, als wuerdest du versuchen, ein von CD bootbares Diskettenimage zu fabrizieren.
    Dabei sollte dir schon klar sein, dass ein CD-ROM keine Diskette ist und entsprechend auch komplett anders funktioniert. Mit einschlaegigen ISO-/Brennprogrammen fabrizierte Images verwenden daher einen speziellen Bootloader, der ein Diskettenlaufwerk simuliert und dann deinen Code spaeter nachlaedt.



  • RawWrite kann AFAIK eben nur fertige Images auf Disketten schreiben oder ein Image aus einer bestehenden Diskette erzeugen! Was ich aber doch brauche ist ein Programm, welches ein neues Image erstellen kann?! Mehrere Dateien als Input, ein Imagefile als Output?! Ich bin nun seit Stunden nach so einem Programm am suchen, aber ohne Erfolg! 😞



  • Ehrlich gesagt verstehe ich nicht ganz, was du vor hast, wozu du ein tolles Programm zum Image-Erstellen brauchst?
    Entweder linkst du deine Dateien geschickt zusammen, oder du haengst sie einfach per HexEditor (oder wenn gewusst wie mit dem copy-Befehl) hintereinander. Die so erzeugte Datei kopierst du mittels Rawrite auf Diskette - fertig.
    Selbst deinen 512Byte grossen Bootloader kannst du wie er ist mittels Rawrite in den Sektor 0 einer Diskette schreiben, um ihn auszuprobieren. Dabei rate ich allerdings zur Vorsicht, da du dir so deine wertvollen Disketten zerstoeren kannst.
    Zum ersten Rumspielen empfehle ich daher sowas wie bochs. Dem kannst du AFAIR auch deinen 512Byte Bootloader als Disketten-Image verfruehstuecken.



  • Hmmm... Wieso können denn dabei die Disketten kaputtgehen? 😮



  • AFAIK: Weil der Bootsektor normalerweise in den ersten Bytes auch Informationen ueber die Diskettengeometrie enthaelt (leider gerade wieder kein Beispiel zur Hand). Meiner Erfahrung nach reagieren viele Systeme nicht gut darauf, wenn diese zB. mit deinem Code ueberschrieben werden.



  • Und wie kann ich denn das verhindern?

    2. Ich habe mir inzwischen mal die Speicheraufteilung angesehen:http://www.in4mation.de/services/memory.html#konventionellerspeicher

    Da ist nichts davon zu erkennen, dass sich im Speicher unterhalb von 07c00h irgendetwas vom BIOS befinden würde. Ausserdem ist daraus ersichtlich, dass der Bildschirmspeicher bei a0000h anfängt, wieso also kann ich den Speicher nur bis zur Adresse 98000h benutzen?

    Ach ja noch was, wieso kann das Programm überhaupt funktionieren, ich habe doch gar kein Codesegment definiert, aber aus irgendeinem Grund funktionierts trotzdem!

    Ich verwirrt! 🙂



  • Ishildur schrieb:

    Und wie kann ich denn das verhindern?

    Indem du diese Daten in deinen Bootsektor einbaust. Schau dir mal hier den Teil zum BPB an (und den Rest vielleicht auch noch 😉 ).

    Ishildur schrieb:

    2. Ich habe mir inzwischen mal die Speicheraufteilung angesehen:http://www.in4mation.de/services/memory.html#konventionellerspeicher

    Da ist nichts davon zu erkennen, dass sich im Speicher unterhalb von 07c00h irgendetwas vom BIOS befinden würde.

    KA, warum das da nicht drin steht, aber es ist so.
    Die BDA geht auch nicht unbedingt genau bis 7C00h - wenn du darunter aber einfach nichts rumschreibst, ohne genau zu wissen was du tust, bist du auf der sicheren Seite. 🙂

    Ishildur schrieb:

    Ausserdem ist daraus ersichtlich, dass der Bildschirmspeicher bei a0000h anfängt, wieso also kann ich den Speicher nur bis zur Adresse 98000h benutzen?

    Wieder gilt: Vorsicht ist die Mutter der Porzellankiste. 😃
    Duerfte aber eigentlich auch bis A0000 problemlos klappen. Musst da oben nur mit der Segmentierung aufpassen, damit du nicht aus versehen in den Grafikspeicher kommst.



  • Hmmmm. Irgendetwas klappte mit meinem Stack nicht! Wie muss ich den Stackpointer initialisieren?

    Im Internet habe ich folgendes gefunden:

    Danach startet der eigentliche Bootloader. Zuerst basteln wir uns einen Stack, dessen Adresse wir auf 0x9000 legen. Den Stackpointer setzen wir dabei auf 0. Während wir unseren Stack zusammenbauen, dürfen wir KEINE Interrupts verwenden!

    Code:
    start:
    cli ; Keine Interrupts verwenden!
    mov ax, 0x9000 ; Adresse des Stack speichern
    mov ss, ax ; Stackadresse festlegen
    mov sp, 0 ; Stackpointer auf 0 setzen
    sti ; Jetzt lassen wir wieder Interrupts zu

    [/quote]

    Ich habe das ein wenig abgeändert:

    cli             ; disable all interrupts as there is still no stack available
    mov ax,MEM_STK  ; copy the address of the stack into ax
    mov ss,ax       ; copy ax into the stacksegment
    xor sp,sp       ; init the stack pointer by zero
    sti             ; enable all interupts
    

    Also, leider funktioniert dass nicht, sobald ich xor sp,sp oder mov sp,00h mache, startet das Programm anschliessend nicht mehr! Was ich sowieso nicht so richtig verstehen kann: Ist es nicht so, dass der Stackpointer dekrementiv ist, müsste man diesen dann nicht wennschon mit bspw. 512 initialisieren?

    Lg Ishildur



  • Ishildur schrieb:

    Hmmmm. Irgendetwas klappte mit meinem Stack nicht! Wie muss ich den Stackpointer initialisieren?[...]
    Was ich sowieso nicht so richtig verstehen kann: Ist es nicht so, dass der Stackpointer dekrementiv ist, müsste man diesen dann nicht wennschon mit bspw. 512 initialisieren?

    Habe ich eigentlich auch schon geschrieben: Stimmt, aber 0 - 2 ist im 16Bit-Register FFFE. Dahin wird auch der erste Wert dann gespeichert.
    Warum dein Code nicht startet, kannst du dir zB. im Bochs debugger anzeigen lassen. Ansonsten kann ich auch nur raten - welchen Wert hat denn zB. MEM_STK?

    Noch eine Anmerkung: AFAIK wird beim Setzen von SS automatisch das Interrupt-Flag bis zur Ausfuehrung des uebernaechsten Befehls geloescht. Ein cli/sti um die 2 Befehle zur Stack-Einrichtung ist also unnoetig.



  • Hmmm, OK, das Problem mit dem Stack konnte ich lösen, ich dachte eben, dass die CPU den Stackpointer vom definierten Stackpointer herunterzählt...

    Irgendwie kriege ich das mit der Diskette lesen nicht gebacken! Woher weiss ich denn, von welchem Track und aus welchem Sektor ich lesen muss? Ist die Sektorgrösse nicht von der Formatierung abhängig?
    Ausserdem, wenn ich nun 15 KBytes auslesen, will, woher weiss ich dann wieviele Tracks und Sektoren dass sind?

    Gibts vielleicht irgendwo ein gutes Tutorial in Bezug auf das lesen von Diskette ohne Dateisystem?

    Lg Ishildur



  • Ishildur schrieb:

    Irgendwie kriege ich das mit der Diskette lesen nicht gebacken! Woher weiss ich denn, von welchem Track und aus welchem Sektor ich lesen muss?

    Du weisst, in welcher Reihenfolge die Daten/Programmteile in deinem Image liegen. Weisst du das nicht, solltest du dir darueber erstmal klar werden.
    Fuer Disketten wird dann AFAIK immer die chs-Adressierung verwendet...
    Wenn du dir dazu noch den Artikel ueber LBA durchliest, wird die Sache hoffentlich klarer... Die Werte fuer die Diskettengeometrie stehen im BPB.

    Ishildur schrieb:

    Ist die Sektorgrösse nicht von der Formatierung abhängig?

    Nein. Von der Laufwerksgeometrie. AFAIK ist das aber eigentlich immer mit der Blockgroesse gleichzusetzen, welche eigentlich auch immer 512 Byte betraegt (mir ist zumindest keine Ausnahme bekannt).

    Ishildur schrieb:

    Ausserdem, wenn ich nun 15 KBytes auslesen, will, woher weiss ich dann wieviele Tracks und Sektoren dass sind?

    Teile die 15kiloByte durch die Blockgroesse. Die so gewonnene Anzahl von Bloecken kannst du mit Hilfe der Laufwerksgeometrie-Daten und der Umrechnungsformel LBA/chs von Wikipedia weiter umrechnen.

    Ishildur schrieb:

    Gibts vielleicht irgendwo ein gutes Tutorial in Bezug auf das lesen von Diskette ohne Dateisystem?

    Kenne keines. Vielleicht bei den OS-Dev-Links.


Anmelden zum Antworten