Software > Coding
gcc, GEMDOS Super und Stackzerstörung
mfro:
--- Zitat von: ari.tao am Fr 19.08.2016, 14:44:56 ---Im übrigen geht die Diskussion jetzt wohl darum, ob man tun darf, was nicht verboten ist, oder nur das, was explizit erlaubt wurde. Im letzteren Fall dürfte man XBIOS_38 wohl gar nicht benutzen...
Man lese das Vorwort im ProfiBuch(10) S.2 .
--- Ende Zitat ---
Die Bemerkung verstehe ich nicht. Supexec() ist offiziell von Atari dokumentiert (Originaltext s.u.). Bloß deine Art der Anwendung eben nicht.
--- Zitat von: ari.tao am Fr 19.08.2016, 14:44:56 ---
--- Zitat von: mfro am Fr 19.08.2016, 07:36:38 ---Folgt leider (genau wie dein Code auch) der auf dem ST sehr verbreiteten Attitüde "wenn's tut, ist's richtig, egal was in der Dokumentation steht"
--- Ende Zitat ---
Gegen diesen Anwurf möchte ich mich strikt verwahren. Ich folge der vorh. Doku. ProfiBuch(10) S.36 sagt deutlich: "BIOS & XBIOS nehmen ihre Parameter auf dem Stack entgegen". In der Beschreibung zu XBIOS_38 steht nix gegenteiliges.
--- Ende Zitat ---
Soweit so gut. Haben wir nie bestritten. Supexec() (die XBIOS-Funktion) nimmt seinen Parameter (die Adresse der auszuführenden Funktion) auf dem Stack entgegen.
Die originale Atari-Dokumentation (die - wie Vieles, was schriftlich von Atari kam - leider ein wenig schwach ist) sagt übrigens genau das (und nicht mehr):
--- Zitat ---(38)
supexec
VOID supexec(LONG codeptr);
codeptr points to a piece of code, ending in an RTS, that is executed in supervisor mode. The code cannot perform BIOS or GEMDOS calls. This function is meant to allow programs to hack hardware and protected locations without having to fiddle with GEMDOS get/set supervisor mode call.
--- Ende Zitat ---
Dein Code (der kein Bestandteil des XBIOS ist) setzt aber weiterhin voraus, daß dein vorher noch weiter oben angelegter Stackframe aus deiner Funktion heraus genauso erreichbar ist. Davon steht kein Wort in der Dokumentation. Die Tatsache, daß das funktioniert - davon bringst Du mich nicht ab - ist meiner Ansicht nach reiner Zufall beziehungsweise eine undokumentierte Eigenschaft der Supexec()-Funktion. Womit wir wieder bei "wenn's funktioniert, ist's richtig" wären.
Offensichtlich bist Du nicht der Einzige, der sich darauf verläßt. Ich habe mal im MiNT-Kernel nachgeschaut, wie der das macht. Eigentlich völlig anders, trotzdem baut er einen Stackframe mit evt. vorhandenen (5) Parametern auf, so daß dein "Trick" auch dort funktionieren würde.
Warum gerade 5? Keine Ahnung. Wahrscheinlich, weil die MiNT-Entwickler ein Programm gefunden haben, das sich genauso auf diese undokumentierte Eigenschaft verlassen hat, das sie gerne mit MiNT lauffähig gehabt hätten. Das brauchte halt 5 Parameter. Der Nächste, der mit 6 Parametern daherkommt, guckt in die Röhre.
Die "fünf Parameter-Sache" ist übrigens auch in MiNT undokumentiert (man sollte sich also lieber nicht drauf verlassen) und war mir bislang unbekannt.
ari.tao:
--- Zitat von: mfro am Fr 19.08.2016, 16:32:31 ---Die Bemerkung verstehe ich nicht.
--- Ende Zitat ---
Dann will ich das noch mal anders (und konkreter) formulieren:
Deine Argumentation:
Daß der Stack bei XBIOS_38 im Trap erhalten bleibt, darf man nicht
annehmen, weil das nicht dokumentiert ist.
Meine Argumentation:
Würde der Stack bei XBIOS_38 im Trap gewechselt, so müßte das
in der Doku stehen (ähnlich wie bei GEMDOS_32). Da in der Doku
nichts dergleichen steht, _muß_ man annehmen, daß der Stack im
Trap erhalten bleibt.
Welche Argumentation die richtige ist, werde ich mit wiedergefundener Doku weiter unten beweisen.
--- Zitat von: mfro am Fr 19.08.2016, 16:32:31 --- Soweit so gut.
--- Ende Zitat ---
Nein, gar nicht gut. Der Nachsatz
--- Zitat von: mfro am Fr 19.08.2016, 07:36:38 ---... egal was in der Dokumentation steht ...
--- Ende Zitat ---
sowie die nachfolgenden Zeilen stellen mich in eine Ecke mit Pfuschern, Freibeutern und anderen Halunken, die Atari geschadet haben.
Da bin ich empfindlich.
--- Zitat --- Die originale Atari-Dokumentation ...
--- Ende Zitat ---
Kannst Du bitte mal genauer zitieren? Das, was Du da gepostet hast über SupExec, scheint mir entweder veraltet oder falsch oder falsch zitiert zu sein. Das ProfiBuch (10) (ich gehe mal davon aus, daß das jeder hat und erspare mir die Abschreiberei) lautet jedenfalls anders. Und das Atari-Compendium, Part_1, p. 4.103 auch. (Ibs. LONG statt VOID!)
So, nun zum hoffentlich endgültig letzten Wort über den Stack in XBIOS_38:
Ich habe die andere der beiden zitierten Literaturen wiedergefunden, nämlich
Brückmann et al. "Atari ST intern" Data Becker GmbH, Düsseldorf 1985
ISBN 3-89011-119-X
Das Buch enthält ab S.207 ´Das BIOS Listing´. Da man davon ausgehen darf, daß es sich nicht um eine Raubkopie handelt, gehört das somit zur offiziellen Doku von Atari. Auf S.220 findet man SupExec; es ist ziemlich kurz:
move.l 4(A7), A0
jmp (A0)
Man sieht, daß mit dem gleichen Stack, von dem der Parameter (im ProfiBuch codeptr genannt) geholt wird, direkt in den Client gesprungen wird.
Ist dies nun endlich überzeugend?
-------
--- Zitat --- ...im MiNT-Kernel nachgeschaut...
--- Ende Zitat ---
Wo genau bitte?!
--- Zitat --- ...auch in MiNT undokumentiert ...
--- Ende Zitat ---
Die MiNT-Quellen sind doch offen, hast Du ja selber grad gesagt, daß Du ´reingeschaut hast! Das _ist_ doch die Doku, was willst Du noch mehr?!
czietz:
--- Zitat von: ari.tao am Sa 20.08.2016, 04:41:04 ---
move.l 4(A7), A0
jmp (A0)
Man sieht, daß mit dem gleichen Stack, von dem der Parameter (im ProfiBuch codeptr genannt) geholt wird, direkt in den Client gesprungen wird.
--- Ende Zitat ---
Weil dieser Stack ein paar Zeilen darüber mit MOVE.L USP, A7 explizit wiederhergestellt wird...
--- Zitat ---Ist dies nun endlich überzeugend?
--- Ende Zitat ---
Bestätigt ein BIOS-Listing aus dem Jahr 1985 (also vermutlich von TOS 1.00), dass alle anderen TOS-Versionen auch das MOVE.L USP, A7 im XBIOS-Dispatcher haben? Vielleicht haben sie es, vielleicht haben sie es nicht. Ich möchte mich nicht darauf verlassen, ohne in jeder einzelnen TOS-Version nachgesehen zu haben und bleibe daher für die entsprechende Stelle in YAART bei Super() in der mit Parametern aufgerufenen Funktion -- bedanke mich aber dennoch für die interessante Diskussion.
--- Zitat ---
--- Zitat --- ...im MiNT-Kernel nachgeschaut...
--- Ende Zitat ---
Wo genau bitte?!
--- Ende Zitat ---
Dort wo man es vermuten würde: in xbios.c.
mfro:
--- Zitat von: ari.tao am Sa 20.08.2016, 04:41:04 ---...
Deine Argumentation:
Daß der Stack bei XBIOS_38 im Trap erhalten bleibt, darf man nicht
annehmen, weil das nicht dokumentiert ist.
...
Meine Argumentation:
Würde der Stack bei XBIOS_38 im Trap gewechselt, so müßte das
in der Doku stehen (ähnlich wie bei GEMDOS_32). Da in der Doku
nichts dergleichen steht, _muß_ man annehmen, daß der Stack im
Trap erhalten bleibt.
--- Ende Zitat ---
Ersteres _darf_ man nicht nur deswegen nicht annehmen, weil es nicht dokumentiert ist, sondern sogar _weil_ es dokumentiert ist. Zwar nicht von Atari (die haben nur dokumentiert, daß ein mc68000 drin ist, außen auf der Schachtel) aber von Motorola. Der Prozessor wurde (in bester Absicht und aus gutem Grund) so gebaut, daß er bei einem Trap in den Supervisor Mode schaltet und ab da das Betriebssystem bis zum abschließenden RTE seinen sorgfältig gehüteten eigenen Supervisor-Stack nutzt, um sich nicht auf "schlampige" (oder sogar bösartige) User-Mode Programme (mit möglicherweise verhunztem Stack) verlassen zu müssen.
Zu erwarten, dass ein Betriebssystem diesen ausgeklügelten Mechanismus (der dazu gedacht ist, das OS vor wildgewordenen User-Programmen zu schützen) aushebelt, aufwendig alles wieder rückgängig macht und noch dazu den Stack im Trap (abhängig vom Prozessor und seinem spezifischen Stackframe-Format) so aufbereitet, daß er aussieht, als ob nichts passiert wäre, ist (für mich zumindest) nicht unbedingt naheliegend (und - aus heutiger Sicht - für ein OS m.E. sogar mehr als hanebüchen).
Nichtsdestotrotz macht TOS genau das (ohne es irgendwo zu dokumentieren) und Du verläßt dich drauf.
Anmerkung: MiNT macht's übrigens richtig und schaufelt - wie bereits geschrieben - (wiederum undokumentiert) lediglich aus Kompatibilitätsgründen die genannten fünf Parameter auf seinen eigenen "heiligen" OS-Stack (xbios.c, Zeile 85ff.).
--- Zitat von: ari.tao am Sa 20.08.2016, 04:41:04 ---Welche Argumentation die richtige ist, werde ich mit wiedergefundener Doku weiter unten beweisen.
--- Ende Zitat ---
Auf deine (meiner Ansicht nach fragwürdigen) "Beweise" werde ich nicht im einzelnen eingehen. Die (nach meiner Kenntnis nach einzige) offizielle Atari-Dokumentation zu Supexec() habe ich (buchstabengetreu und komplett) gepostet. Sie stammt aus "A Hitchhiker's Guide to the BIOS" (ich meine mich darüber hinaus noch an einen gleichlautenden, schlecht kopierten "Fresszettel" im Atari-Developer's Kit zu erinnern, finde den aber gerade nicht). Alles andere ist entweder dort abgeschrieben oder eine mehr (Profibuch) oder weniger (die mit dem roten Einband) professionelle Interpretation des ROM-Inhalts (die Einschätzung der Professionalität ist meine eigene, der muss man nicht unbedingt folgen). Jedenfalls ist das *nicht* die offizielle Dokumentation (die konnte nur von Atari kommen).
Dass bei derart dünner Dokumentation die Interpretationen herhalten mussten, daran ist Atari - zumindest zum Teil - natürlich selbst schuld. Ich will auch das Profibuch ganz bestimmt nicht schlecht machen. Angesichts der außerordentlich knappen Atari-Doku war es toll, daß es "die Bibel" überhaupt gab und die Jungs waren die ersten und einzigen, die zwischen "offiziell dokumentiert" und "aus dem Verhalten interpretiert" unterschieden haben. Nichtsdestotrotz ist es eben *nicht* die offizielle Doku.
--- Zitat von: ari.tao am Sa 20.08.2016, 04:41:04 ---Die MiNT-Quellen sind doch offen, hast Du ja selber grad gesagt, daß Du ´reingeschaut hast! Das _ist_ doch die Doku, was willst Du noch mehr?!
--- Ende Zitat ---
Hier zeigt sich m.E. (d)ein grundsätzliches Mißverständnis. Wenn der Quellcode (oder auch das Disassembly) die Dokumentation wäre, könnte man ja nicht einen einzigen Buchstaben mehr dran ändern (es könnte sich ja jemand auf genau den verlassen haben).
Eine API-Dokumentation beschreibt das Interface und so viel vom Verhalten, wie sich nicht mehr ändern wird. Alles andere ist Interpretation.
mfro:
--- Zitat von: czietz am So 07.08.2016, 10:48:10 ---... Insbesondere braucht diese Schleife mit gcc ca. 40%(!) länger als mit Pure C.
--- Code: --- while (p>start_local) {
if ((x = *(--p)) != patt2_local) {
bad = x;
}
*p = patt1_local;
}
--- Ende Code ---
Ich hätte ja gedacht, dass ein moderner Compiler gegen einen aus dem vergangenen Jahrtausend meilenweit überlegen ist. Wohl falsch gedacht...
--- Ende Zitat ---
Irgendwie will mir das noch nicht ganz aus dem Kopf. Ich habe den leisen Verdacht, daß das mit pointer aliasing zu tun hat und sich der gcc dadurch in einen Optimierungsversuch versteigt, der letztendlich in schlechterem Code resultiert.
--- Zitat ---gcc -O3 hält den Pointer p in zwei Adressregistern vor, einen zum Lesen und Beschreiben der Speicherstelle und einen zum Vergleich mit start.
--- Ende Zitat ---
Pointer aliasing könnte der Grund dafür sein. p könnte ja schließlich patt2 überlaufen.
Daraufhin habe ich versucht, p als __restrict__ zu definieren, aber "unser" gcc kennt zwar das Schlüsselwort und akzeptiert es, erzeugt aber genau denselben Code (scheint also nichts Rechtes damit anzufangen zu wissen).
Navigation
[0] Themen-Index
[#] Nächste Seite
[*] Vorherige Sete
Zur normalen Ansicht wechseln