PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Wie viel RAM in .COM-Dateien verfügbar?


NerdIII
12.04.2005, 02:50
Hallo an alle!
Kurze frage an erfahrene Programmierer: Wenn ich unter DOS oder im DOS-Emulator von Win2k eine .COM Datei lade, welchen Speicherbereich, darf ich maximal nutzen? Im Moment stelle ich mir das so vor:
- DOS sucht sich einen freien zusammenhängenden Speicherblock von 64k
- DOS lädt die .COM Datei an den Anfang dieses Blocks
- DOS setzt alle Segment-Zeiger auf den Block und startet das Programm
- Mehr Speicher gibt's nicht, verkleinern kann ich den 64k-Block allerdings schon, was aber für mich sinnlos erscheint.

Stimmen meine Annahmen?
Für jede Insiderinfo gibt es einen Keks und ein Bier.

Gruß, Marco
(Forumsneuling)


Xpyder
12.04.2005, 04:10
Also aus meiner Sicht würde ich sagen, stimmt genau so.
Es gibt wohl auch einige (unkonventionelle) Möglichkeiten,
anderen Speicher zu benutzen, habe ich mal gelesen...
Aber normal entspricht genau das, was Du gesagt hast, dem
"Standard" für COM-Dateien:
DOS sucht sich einen 64kB Bereich und klatscht die
COM-Datei original wie sie ist, so in diesen Bereich. COM
sind reiner Assemblercode, haben keinen "Header" (wie z.B.
EXE Dateien). Er startet die Ausführung mit genau dem
ersten Befehl in diesem 64kB-Bereich.
Also, zumindest die Segmente CS und DS werden definitiv
auf den Segmentstart gesetzt. Glaube auch SS.
Btw: Info ist umsonst. Bier mag ich eh nicht und Kekse kann
ich mir selbst leisten.

Pukys
12.04.2005, 09:39
Also aus meiner Sicht würde ich sagen, stimmt genau so.
Es gibt wohl auch einige (unkonventionelle) Möglichkeiten,
anderen Speicher zu benutzen, habe ich mal gelesen...
Aber normal entspricht genau das, was Du gesagt hast, dem
"Standard" für COM-Dateien:
DOS sucht sich einen 64kB Bereich und klatscht die
COM-Datei original wie sie ist, so in diesen Bereich. COM
sind reiner Assemblercode, haben keinen "Header" (wie z.B.
EXE Dateien). Er startet die Ausführung mit genau dem
ersten Befehl in diesem 64kB-Bereich.
Also, zumindest die Segmente CS und DS werden definitiv
auf den Segmentstart gesetzt. Glaube auch SS.
Btw: Info ist umsonst. Bier mag ich eh nicht und Kekse kann
ich mir selbst leisten.

Stimmt soweit, bis auf eine Kleinigkeit. Das .COM-Image wird an das Offset 0100h in das Segment geladen und ab dort ausgeführt, direkt davor liegt der PCB. Der Programloader schreibt einen PCB, initialisiert aber *keinen* Stack! Ein COM-Programm startet erst einmal ohne Stack, bzw. mit dem Stack der aufrufenden Instanz (zumindest war das früher so). Aber auf diesen Stack wird vom Loader eine 0h gePUSHed.
(Kleiner Tip: Der PCB beginnt immer mit einem INT 20h, so daß man das Programm auch mit einem RET NEAR beenden kann. Da initial ein 0h auf dem Stack liegt, wird damit ein INT20h ausgeführt, was das Programm beendet!)

NerdIII
12.04.2005, 16:36
Ja, dass mit dem Offset musste ich schon erfahren, hab öfter mal das org 100h vergessen und mir damit die Adressen meiner Zeichenketten verhaun ;) .
Die Sache mit dem RET NEAR ist mir nicht ganz geheuer. Unter Windows 2000 steht an Adresse 0 kein Interrupt sondern irgendwas zufälliges. Hier mal die ersten 256 Bytes in Dezimaldarstellung:
25 32 255 159 0 154 240 254 29 240 222 1 240 3 75 1 240 3 86 1 240 3 240 3 1 1 1 0 2 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 249 4 228 255 175 6 20 0 24 0 175 6 255 255 255 255 0 0 0 0 5 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 25 33 23 0 0 0 0 0 0 0 0 0 0 32 32 32 32 32 32 32 32 32 32 32 0 0 0 0 0 32 32 32 32 32 32 32 32 32 32 32 0 0 0 0 0 0 0 0 0 13 47 114 32 64 19 18 18 15 110 17 36 46 18 110 17 13 50 92 10 111 115 120 13 110 116 11 114 115 116 252 116 122 117 110 13 13 115 32 40 118 111 114 32 10 111 115 120 46 11 120 11 32 18 97 10 11 110 41 13 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0

Aber da du den PCB nicht wunderbar als Textpuffer verwenden, oder erschlägt mich mein Betriebssystem, wenn ich da rumpfusche?

Pukys
12.04.2005, 22:07
Ja, dass mit dem Offset musste ich schon erfahren, hab öfter mal das org 100h vergessen und mir damit die Adressen meiner Zeichenketten verhaun ;) .
Die Sache mit dem RET NEAR ist mir nicht ganz geheuer. Unter Windows 2000 steht an Adresse 0 kein Interrupt sondern irgendwas zufälliges. Hier mal die ersten 256 Bytes in Dezimaldarstellung:
[...]
Aber da du den PCB nicht wunderbar als Textpuffer verwenden, oder erschlägt mich mein Betriebssystem, wenn ich da rumpfusche?

PCB = PSP... Sorry, mein Fehler. Ich hatte Pogram Control Block im Hinterkopf, es heißt aber Program Segment Prefix.
Laut Doku (die eigentlich auch für Windows und NTVDMs gelten sollte) beginnt das PSP immer mit CD 20 (INT 20h), eben damit das RET bei Programmende funktioniert (dies ist aus Kompatiblitätsgründen so. Kompatiblität zu CP/M...... :-)
Als Textbuffer ist das PSP bedingt brauchbar: Ab Byte 80 liegt die Kommandozeile (bis 127), aber ab Byte 128 liegt die Standard-DTA (Disk Transfer Area), d.h. bei Filezugriffen wird dieser Bereich von DOS als Fixup benutzt, und zerstört u.U. dessen Inhalt. Wenn du keine Filezugriffe benötigst, kannst du die DTA gern als Zwischenpuffer benutzen. :-)

NerdIII
13.04.2005, 00:24
Lol, Asche über mein Haupt und danke Pukys. Ich habe gerade festgestellt, dass meine tolle Routine zum Ausgeben von Dezimalzahlen nicht nur führende Nullen ignoriert, sondern auch alle anderen, bis auf die letzte! :mauer:
Wenn man sich dann mal die 25, die ich vermeintlich am Anfang des Segments hatte anguckt und 'ne 0 einfügt wird es 205 = CD.
Ok, schade wird nix mit 256 Byte Puffer an Offset 0 *g*, aber um mal eine Zahl einzulesen oder Variablen zu Puffern reicht es ja. Ich bastel mir nämlich gerade einen DOS-Gif-Viewer als .COM-Datei. Sozusagen die kleinste Slideshow der Welt. Ein netter Bootloader wäre das auch, aber das geht dann schon zu weit. :D

Pukys
13.04.2005, 09:24
Lol, Asche über mein Haupt und danke Pukys. Ich habe gerade festgestellt, dass meine tolle Routine zum Ausgeben von Dezimalzahlen nicht nur führende Nullen ignoriert, sondern auch alle anderen, bis auf die letzte! :mauer:
Wenn man sich dann mal die 25, die ich vermeintlich am Anfang des Segments hatte anguckt und 'ne 0 einfügt wird es 205 = CD.

Wow, das nenne ich mal einen wirklich kreativen Fehler! Damit hast du dir soeben den awkward error of month-Award gesichert. :D You made my day.

Ok, schade wird nix mit 256 Byte Puffer an Offset 0 *g*, aber um mal eine Zahl einzulesen oder Variablen zu Puffern reicht es ja.

Dafür sollte es mehr als ausreichend sein. Wie gesagt - solang der Puffer Filezugriffe nicht überleben muß, ist das kein Problem, aber das PSP komplett zu überschreiben ist keine wirklich gute Idee. Was ich eher gemacht habe, ist die Programminitialisierung wegzuwerfen, d.h. der Initcode, der eh nur einmal ausgeführt werden muß, wurde auf 256 Bytes aufgebläht (MASM-Preprocessing läßt grüßen) und dann irgendwann burtal überschrieben, bzw. von Entpackroutine gekilled (Runtimepacking ist bei .COMs ok :-).
Der Stack eignet sich auch wunderbar für solche Dinge!

Ich bastel mir nämlich gerade einen DOS-Gif-Viewer als .COM-Datei. Sozusagen die kleinste Slideshow der Welt. Ein netter Bootloader wäre das auch, aber das geht dann schon zu weit. :D

Bootloader? Bootstrap-Loader?

butterkeks
13.04.2005, 17:41
Kann ein COM Programm nicht mit ax=0x48 und int 21h noch weiteren Speicher auf dem Heap holen?
(Diesen Speicher kann man natürlich nicht für das COM File, also den Code, selbst nutzen, aber für Daten schon)

NerdIII
13.04.2005, 22:29
Kann ein COM Programm nicht mit ax=0x48 und int 21h noch weiteren Speicher auf dem Heap holen?
(Diesen Speicher kann man natürlich nicht für das COM File, also den Code, selbst nutzen, aber für Daten schon)

Schien bei mir nur in der DOS-Box und ohne Batch-Datei zu gehen. (Hab immer mit Batch-Datei compliert und gestartet und mich gewundert.) Unter purem DOS scheint es auch nicht zu gehen.
Aber wie gesagt: Standalone in der Win2000 Box, gab die Funktion zumindest keine Fehlermeldung. Bug oder Feature *g*?

Pukys
14.04.2005, 11:47
Schien bei mir nur in der DOS-Box und ohne Batch-Datei zu gehen. (Hab immer mit Batch-Datei compliert und gestartet und mich gewundert.) Unter purem DOS scheint es auch nicht zu gehen.
Aber wie gesagt: Standalone in der Win2000 Box, gab die Funktion zumindest keine Fehlermeldung. Bug oder Feature *g*?

COM-Porgramme bekommen von DOS erst mal den kompletten freien Speicher zugeschlagen, wenn sie sich als TSR installieren wollen, müssen sie den erst mal freigeben. D.h. DOS-COMs können schon recht Böse aasen, man muß halt nur die MCBs im Blick behalten, daß man nicht "aus Versehen" belegte Speicherbereiche überschreibt. COM-Programme entsprechen halt dem TINY-Speichermodell von C.

Aber meine Frage noch mal: Was verstehst du unter Boot-Loader? Wenn du den Bootstrap-Loader der Festplatte meinst, der im MBR sitzt, da könnte ich auch noch einiges zu erzählen...

NerdIII
15.04.2005, 17:30
Ja, den meinte ich, aber das war wirklich nur eine fixe Idee! Um da einen netten grafischen Hintergrund einzubauen oder eine GIF-Animation, bräuchte ich a bisserl mehr als 512 Bytes und dann muss ich ja vermutlich zumindest eines meiner Dateisysteme NTFS oder EXT2 gut kennen.
Andererseits bin ich ziemlich neugierig, wie der ganze Kram so funktioniert. Erzähl mal :D . Hast du mal so einen Bootstrap-Loader geschrieben?

NerdIII
18.04.2005, 01:08
Puh, hat tatsächlich geklappt. In Hochsprachen kann man es sich wirklich einfacher machen. In Assembler wird so ein GIF-Decoder schon mal unübersichtlich. Aber nun hab ich doch endlich eine vorläufige Version fertig!
Einfach an die .COM Datei eine GIF-Datei anhängen (max. ca. 50 KB, 320x200 Pixel, nicht animiert) und ausführen.
Als nächstes schreib ich mir davon einen Bootsektor, der dann eine ganze Diskette anzeigt. Quasi eine VFD (Video-Floppy-Disk) :p