ENGLISH VERSION |
|
Links | | | Forum | | | Kommentare | | | News melden |
Chat | | | Umfragen | | | Newsticker | | | Archiv |
amiga-news.de Forum > Programmierung > gcc und Assembler Code | [ - Suche - Neue Beiträge - Registrieren - Login - ] |
-1- | [ - Beitrag schreiben - ] |
25.10.2005, 10:45 Uhr Mad_Dog Posts: 1944 Nutzer |
Hallo, Ich bin gerade dabei ein altes Programm (stammt nicht von mir) vom Borland C++ Builder auf gcc zu "portieren". Unter anderem ist auch x86 Assembler Code enthalten: code:unsigned short int high(unsigned long a) { unsigned short int back; asm { push eax mov eax,[a+2] mov back,ax pop eax }; return back; } Leider meckert der gcc (ist gcc für x86). Klar kann man das auch anders machen, aber ich wüsste trotzdem gerne, wie das ANSI C++ konform auszusehen hat. -- http://www.norman-interactive.com [ - Antworten - Zitieren - Direktlink - ] |
25.10.2005, 20:04 Uhr Mazze Posts: 263 Nutzer |
@Mad_Dog: Ganz einfach: ANSI C++ kennt kein "asm". Wenn doch alle Probleme so einfach wären :-) Im ernst: Soweit ich weiß, hat GCC einen plattformunabhängigen Assembler. Da Du das sowieso umschreiben müsstest, kannst Du auch gleich C nehmen. -- Meine Homepage [ - Antworten - Zitieren - Direktlink - ] |
26.10.2005, 09:21 Uhr Mad_Dog Posts: 1944 Nutzer |
Zitat: Also laut Bjarne Stroustrup's "Die C++ Programmiersprache" kennt C++ sehr wohl auch Assembler Code Sequenzen. Eigentlich müsste es so funktionieren, wie in meinem Posting dargestellt - geht aber irgendwie nicht... -- http://www.norman-interactive.com [ - Antworten - Zitieren - Direktlink - ] |
26.10.2005, 09:41 Uhr gni Posts: 1106 Nutzer |
Zitat:Nein. Zitat:Und das ist auch gut so! Machs in C(++) und der Fall ist erledigt. [ - Antworten - Zitieren - Direktlink - ] |
26.10.2005, 09:45 Uhr gni Posts: 1106 Nutzer |
Zitat:Was soll ein "plattformunabhängiger Assembler" sein? Wenn Du x86 Befehle verwendest, dann eignet sich das nur für x86. Zudem benutzt der GCC eine andere Art von Inline-Asm. Das kann man im Abschnitt "extended Asm" der GCC-Dokumentation nachlesen. [ - Antworten - Zitieren - Direktlink - ] |
26.10.2005, 09:45 Uhr Solar Posts: 3680 Nutzer |
Zitat: Nicht ganz. Aus besagtem Buch: Zitat: Das heißt, Du must in jedem Fall die Dokumentation Deines Compilers befragen, da C++ über den Inhalt, Syntax etc. des string-literals keine Aussagen macht. http://www.mega-tokyo.com/osfaq2/index.php/InlineAssembly http://gcc.gnu.org/onlinedocs/gcc-4.0.2/gcc/Extended-Asm.html#Extended-Asm [ Dieser Beitrag wurde von Solar am 26.10.2005 um 09:46 Uhr editiert. ] [ - Antworten - Zitieren - Direktlink - ] |
26.10.2005, 09:48 Uhr Solar Posts: 3680 Nutzer |
Zitat: GNU 'as' aus dem binutils-Package. Die "plattformunabhängigkeit" bezieht sich darauf, das die 'as'-Varianten für die unterschiedlichen Plattformen soweit möglich dieselben Kommandozeilenparameter und dieselbe Syntax haben. Zitat: Und eben dieses, durch ein einleitendes "asm" gekennzeichnetes Compiler-spezifisches Verhalten ist durch den C++-Standard abgesegnet. [ - Antworten - Zitieren - Direktlink - ] |
26.10.2005, 12:01 Uhr Mazze Posts: 263 Nutzer |
Zitat: Ups, ich hatte angenommen, dass der inline-assembler prozessorunabhängig ist. -- Meine Homepage [ - Antworten - Zitieren - Direktlink - ] |
26.10.2005, 12:21 Uhr Solar Posts: 3680 Nutzer |
Kann er nicht. GCC gibt's u.a. für 68k, PPC, x86... jeder dieser Prozessoren mit eigenen Befehlen, Adressierungsarten etc. - ein wirklich plattformunabhängiger Assembler ist nicht möglich. GNU 'as' ist halt das den Maschinencode erzeugende "Backend" von GCC. Da hat man drauf geachtet, das der Teil von GCC, der z.B. vom PPC-'as' auf den 68k-'as' angepaßt werden muß, möglichst klein ist. Das ist aber auch schon alles - ein PPC-Assembler kann mit "SYSCALL" oder "IDIV" nun einmal nichts anfangen... [ - Antworten - Zitieren - Direktlink - ] |
26.10.2005, 13:54 Uhr Mad_Dog Posts: 1944 Nutzer |
@Solar: Danke! Natürlich hab diesen Code-Abschnitt jetzt durch "normale" C/C++ Lowlevel Operationen ersetzt - ist ja auch einfacher. Wenn mal Zeit ist, schau ich mir die Assembler-Sache trotzdem nochmal genauer an... code:// folgendes gilt nur für LittleEndian Systeme, // deren breite für Long exakt 4 Byte ist. inline unsigned short int low(unsigned long a) { return (int)a; // loword holen }; inline unsigned short int high(unsigned long a) { return (int)(a>>16); // highword holen }; Das gilt aber nur für x86. Das Ziel ist es, das Programm (über 300000 Zeilen C++ Code) von Borland C++ Builder (x86 Windows) auf gcc (UltraSparc Solaris) zu portieren. Und da ist leider jede Menge Zeug drin, was nicht nach ANSI/ISO Standard ist. Für die UltraSparc Kiste muß ich dann eben die Byte Order und Breite des Typs long beachten usw... -- http://www.norman-interactive.com [ Dieser Beitrag wurde von Mad_Dog am 26.10.2005 um 17:21 Uhr editiert. ] [ - Antworten - Zitieren - Direktlink - ] |
26.10.2005, 17:08 Uhr gni Posts: 1106 Nutzer |
Zitat:Der Kommentar ist falsch. Der Code funktioniert auch auf nicht-LittleEndian Systemen... Zitat:Du solltest mit "& 0xffff" den Wert begrenzen. Und warum mit (int) casten?code:inline unsigned short int low(unsigned long a) { return (int)a; // loword holen }; Zitat:Warum soll der obige Code nur auf x86 laufen?code:Das gilt aber nur für x86.inline unsigned short int high(unsigned long a) { (int)(a>>16); // highword holen }; Zitat:Byteorder und Typgröße ist nur interessant, wenn Du mit Binärdaten einlesen/speichern mußt. [ - Antworten - Zitieren - Direktlink - ] |
26.10.2005, 17:13 Uhr Mad_Dog Posts: 1944 Nutzer |
Zitat: "Laufen" tut er sicher auch auf UltraSparc Systemen - nur macht er da nicht das richtige. Überleg Dir mal, was passieren würde, wenn die Byteorder anders wäre (Big Endian statt Little Endian) und ich den Shift-Operator verwende... Zitat:Zitat:Byteorder und Typgröße ist nur interessant, wenn Du mit Binärdaten einlesen/speichern mußt. Und genau darum geht's bei der Sache. -- http://www.norman-interactive.com [ Dieser Beitrag wurde von Mad_Dog am 26.10.2005 um 17:21 Uhr editiert. ] [ - Antworten - Zitieren - Direktlink - ] |
26.10.2005, 17:31 Uhr Holger Posts: 8116 Nutzer |
Zitat:Solange Du nicht mit pointern auf dem Speicher operierst, ist es vollkommen unerheblich, in welcher Reihenfolge die bytes im Speicher liegen. (x&0xff) betrifft immer das niederwertigste Byte, (x&0xff)>>8 immer das nächsthöhere. Zitat:Dann sollte der Code so gestaltet werden, daß bereits beim Einlesen/Speicherzugriff die Umwandlung stattfindet. Aus einem Speicherbereich ein long zu lesen, um ihn dann mittels shiften und maskieren umzudrehen, ist unlogisch/schlecht lesbar UND ineffizient.Zitat:Und genau darum geht's bei der Sache. mfg -- Good coders do not comment. What was hard to write should be hard to read too. [ - Antworten - Zitieren - Direktlink - ] |
27.10.2005, 09:17 Uhr gni Posts: 1106 Nutzer |
Zitat:Du solltest Deinen Hinweis selber befolgen. Dann fällt Dir hoffentlich auf, das der von Dir gezeigte Code auf jeder Byteorder funktioniert. Zitat:Dann mach das Ändern der Bytereihenfolge auch an der richtigen Stelle. Mit denen von Dir geposteten Funktionen erreichst Du _nichts_. FWIW, Du solltest mit char-Feldern arbeiten, wie zb. die GNU binutils.Zitat:Und genau darum geht's bei der Sache. [ - Antworten - Zitieren - Direktlink - ] |
27.10.2005, 09:53 Uhr Mad_Dog Posts: 1944 Nutzer |
Zitat: Ich glaube, wir reden aneinander vorbei. Hier geht's nicht darum eine Umwandlung von Little auf Big Endian vorzunehmen, sondern das High- bzw Low- Word aus einem Long zu lesen, also die oberen oder unteren 16 Bit von 32. Hier nochmal ein Beispielcode: code:#include <cstdlib> #include <iostream> using namespace std; int main(int argc, char *argv[]) { cout << "int : " << sizeof(int) << " byte" << endl; cout << "short int : " << sizeof(short int) << " byte" << endl; cout << "char : " << sizeof(char) << " byte" << endl; cout << "long : " << sizeof(long) << " byte" << endl; const long l = 0xA4B3C2D1; unsigned short hi,lo; lo = (int)l; // loword holen hi = (int)(l>>16); // highword holen cout << hex << l << endl; cout << hex << "lo=" << lo << endl << "hi=" << hi << endl; cin.get(); return 0; } Die Sache mit der "Wandlung" habe ich mal in eimem BMP Texturloader für Amiga gebraucht... dort habe ich tatsächlich den Shifter zum Vertauschen der Bytes verwendet. Siehe hier: ftp://de.aminet.net/pub/aminet/dev/src/GL_BMP_Load_11.lha -- http://www.norman-interactive.com [ - Antworten - Zitieren - Direktlink - ] |
27.10.2005, 12:38 Uhr Holger Posts: 8116 Nutzer |
Zitat:Und dieser Code macht auf allen Systemen das Gleiche, egal ob BigEndian oder LittleEndian. Glaub doch einfach mal denen, die schon etwas länger mit C zu tun haben. (Obwohl das nicht unbedingt C-spezifisch ist.) Nur, wofür das gut sein soll, ist nicht klar. Dieser Code hat nichts mit I/O oder anderer Form von externen Daten zu tun. Zitat:DAS ist ja auch völlig anderer Code. Das BMP-Format benutzt tatsächlich eine definierte Endianess, die von der des Systems abweichen kann... mfg -- Good coders do not comment. What was hard to write should be hard to read too. [ Dieser Beitrag wurde von Holger am 27.10.2005 um 12:39 Uhr editiert. ] [ - Antworten - Zitieren - Direktlink - ] |
27.10.2005, 12:50 Uhr Mad_Dog Posts: 1944 Nutzer |
Zitat: Hab's zwar noch nicht ausprobiert, aber wenn Du das sagst. Ich dachte eben, wenn die Reihenfolge anders ist, würde es eine Rolle spielen, ob ich nach links oder rechts schiebe... Zitat:Zitat:DAS ist ja auch völlig anderer Code. Das BMP-Format benutzt tatsächlich eine definierte Endianess, die von der des Systems abweichen kann... Im aktuellen Fall geht es darum, gds Dateien einzulesen. Aber ich denke, es hat sich erübrigt, da diese Codesequenz überflüssig geworden ist. -- http://www.norman-interactive.com [ Dieser Beitrag wurde von Mad_Dog am 27.10.2005 um 12:51 Uhr editiert. ] [ - Antworten - Zitieren - Direktlink - ] |
27.10.2005, 15:21 Uhr Holger Posts: 8116 Nutzer |
Zitat:Es spielt eine Rolle, ob Du nach links oder rechts schiebst. Ein Bit nach links schieben ist gleichbedeutend mit Verdoppeln, eins nach rechts mit Halbieren. Nun stell Dir mal vor, wie es sich programmieren würde, wenn man auch noch bei Multiplikation und Division die Byteorder berücksichtigen müßte... mfg -- Good coders do not comment. What was hard to write should be hard to read too. [ - Antworten - Zitieren - Direktlink - ] |
27.10.2005, 18:05 Uhr Mad_Dog Posts: 1944 Nutzer |
Zitat: Das war eben mein Denkfehler: Nicht links oder rechts, wie wenn man die Zahl aufs Papier schreibt, sondern n Bit in Richtung höherwertiges oder niederwertiges Bit schieben. Danke! -- http://www.norman-interactive.com [ - Antworten - Zitieren - Direktlink - ] |
27.10.2005, 21:17 Uhr Holger Posts: 8116 Nutzer |
Zitat: Hmm, wenn Du die Zahl binär aufschreibst und wie die meisten Mitteleuropäer von links nach rechts schreibst, dann kommts doch hin. Ansonsten wärst Du der erste mir bekannte Mensch, der Zahlen in LittleEndian aufschreiben würde. mfg -- Good coders do not comment. What was hard to write should be hard to read too. [ - Antworten - Zitieren - Direktlink - ] |
28.10.2005, 09:27 Uhr Mad_Dog Posts: 1944 Nutzer |
Zitat: Also wenn ich einen Schreibtischtest für ein Programm mache, oder mir eine Binärdatei anschaue (oder gar als Hexzahlen ausdrucke), dann habe ich die Zahlen sehr wohl als Little Endian vor mir, falls diese im Rechner auch tatsächlich so gespeichert werden. -- http://www.norman-interactive.com [ - Antworten - Zitieren - Direktlink - ] |
28.10.2005, 11:12 Uhr Solar Posts: 3680 Nutzer |
C selbst kennt kein "byte". Es kennt nur char, short, int, long, (long long). Und im Hinblick auf die Shift-Operatoren steht das höchstwertigste Bit links. Die Probleme mit Low / Big Endian gibt's immer erst beim Einlesen und Rausschreiben, z.B. wenn Du einen long einliest, der aber tatsächlich aus zwei shorts besteht, oder auf einer Maschine mit Endianess X Binärdaten einliest, die auf einer Maschine mit Endianess Y geschrieben wurden. Solange Du Dich auf einer Maschine bewegst und die "richtigen" Datentypen für den Inhalt verwendest, merkst Du in C von Endianess gar nichts. Und was Dein Beispiel angeht... gesunde Paranoia anlegen und Ausgabefunktionen, Hexeditor etc. auf implizite Konvertierungen prüfen... [ - Antworten - Zitieren - Direktlink - ] |
28.10.2005, 12:01 Uhr Mad_Dog Posts: 1944 Nutzer |
Zitat: Eben. x86 und UltraSparc sind hier eben verschieden. Die gds Datei wird von Cadence unter Solaris geliefert und soll in einem Programm auf Windows verarbeitet werden, welches es jetzt nach Solaris zu portieren gilt. -- http://www.norman-interactive.com [ - Antworten - Zitieren - Direktlink - ] |
28.10.2005, 12:09 Uhr Holger Posts: 8116 Nutzer |
Zitat: Du scheinst Dir selbst das Leben schwer machen zu wollen. Ich bin mir sicher, daß Dein Schreibtisch von Endianess erst mal keine Ahnung hat. Und es ist auch nicht sinnvoll, sich ein Datum mit einem HexEditor byteweise ausgeben zu lassen, wenn es sich bei dem Wert nicht um eine Abfolge von bytes handelt. Wenn Du einen Algorithmus in Gedanken durchgehen willst, dann solltest Du bei einer Zahl auch nur an eine Zahl denken und nicht an eine Folge von n bytes und an deren Reihenfolge. Und dann frage auch den Debugger nach dem int-Wert und nicht nach eine hexadezimalen Abfolge von bytes. mfg -- Good coders do not comment. What was hard to write should be hard to read too. [ - Antworten - Zitieren - Direktlink - ] |
28.10.2005, 12:48 Uhr Mad_Dog Posts: 1944 Nutzer |
@Holger: Du wirst es doch wohl nicht bestreiten wollen, daß es durchaus sinnvoll ist, eine Binärdatei in einem Hexeditor anzuschauen, wenn man für das jeweilige (binär) Format (z.B. gds) eine Lade/Speicherroutine schreiben will, oder? Also ich für meinen Teil drucke mir in solch einem Fall eine kleine Testdatei aus - dann kann ich darin munter Stellen mit dem Textmarker markieren, Anmerkungen dazukritzeln usw. . -- http://www.norman-interactive.com [ - Antworten - Zitieren - Direktlink - ] |
28.10.2005, 13:55 Uhr Holger Posts: 8116 Nutzer |
Zitat:Doch, halte ich für sinnlos. Entweder ich besitze eine Dokumentation für das Dateiformat oder ich lasse es bleiben, insbesondere würde ich lassen, wenn ich nichtmal verstehe, was die Operatoren in C machen. Wenn ich dagegen eine Laderoutine für ein bekanntes Format schreiben will, wäre es Zeitverschwendung, eine Datei im Hexdump anzuschauen, wenn ich die Laderoutine selbst mit printf's füllen kann, die den jeweiligen Wert in seiner natürlich Form, also Zahlen als Dezimalwert in ihrem richtigen Wertebereich statt als bytes, und Flags als Hex-Wert oder sogar symbolisch ausgeben. Das gibt mir viel mehr Informationen und kann mit einem Dutzend Beispieldateien aufgerufen oder auch schrittweise debugged werden. Zitat:und heraus kommt eine Laderoutine, die genau diese eine Datei einlesen kann? Ein Hexviewer kann in wenigen Fällen den Debugvorgang ergänzen, aber da weder Mensch noch Computer auf ein einem HexDump operieren, ist er keinesfalls die erste Wahl bei den Hilfmitteln. mfg -- Good coders do not comment. What was hard to write should be hard to read too. [ - Antworten - Zitieren - Direktlink - ] |
28.10.2005, 14:01 Uhr Solar Posts: 3680 Nutzer |
Zitat: Nur wenn einem bewußt ist, das ein Hexeditor durchaus selbst eine Umwandlung zwischen Endianess vornehmen mag. Gibt Dein Hexdumper in "native format" aus, immer Big Endian, oder immer Little Endian? Solange Du diese Frage nicht aus der Hüfte beantworten kannst, hast Du bei solchen Reverse-Engineering-Versuchen ein Problem. Von den übrigen Problemen, die Holger angesprochen hat, mal ganz abgesehen... [ - Antworten - Zitieren - Direktlink - ] |
28.10.2005, 14:01 Uhr Mad_Dog Posts: 1944 Nutzer |
[quote] Original von Holger: Zitat: Hab ich je behauptet, daß ich blindes Reverse Engineering betreibe? Natürlich habe ich eine Dokumentation zum Dateiformat. Allerdings kann es nicht schaden, wenn man ein konkretes Beispiel anschaut und im Falle einer Speicherroutine das ist Ergebnis mit dem soll Ergebnis vergleicht. -- http://www.norman-interactive.com [ - Antworten - Zitieren - Direktlink - ] |
28.10.2005, 19:40 Uhr Holger Posts: 8116 Nutzer |
Zitat:Ich ja auch nicht. Wenn ich eine Dokumentation zu einem Dateiformat habe, brauche ich aber keinen Hex-Dump. Zitat:Das "Anschauen" geht aber viel leichter, wenn man statt auf einen Hexdump auf den Output einer selbst geschriebenen Leseroutine schaut, die die Einträge der Struktur in sinnvollen, den Datentypen entsprechenden Ausgabeformaten ausgibt. Aber das hatte ich oben ja schon geschrieben. Dann hast Du nämlich hinterher auch schon die Laderoutine fertig. Und dieser source-code ist besser als jede Notiz auf einem Schmierpapier. Denn diese Art der Notiz kann sowohl von der Maschine als auch jedem anderen Programmierer verstanden werden, mit dem Du Dich über das Dateiformat oder Deine Software austauschen möchtest. mfg -- Good coders do not comment. What was hard to write should be hard to read too. [ - Antworten - Zitieren - Direktlink - ] |
-1- | [ - Beitrag schreiben - ] |
amiga-news.de Forum > Programmierung > gcc und Assembler Code | [ - Suche - Neue Beiträge - Registrieren - Login - ] |
Impressum |
Datenschutzerklärung |
Netiquette |
Werbung |
Kontakt
Copyright © 1998-2024 by amiga-news.de - alle Rechte vorbehalten. |