Anfänger versteht das Problem bei der Fehlermeldung nicht
-
Hallo,
ich habe zum ersten mal was mit Assembler gemacht bzw. versuche zu machen und es geht natürlich erst mal schief ^^
Also ich will mit Assembler erst mal nur was mit meinem GNU C++ Compiler machen. Also Assembler in ein C++ Programm einbauen. Da ich hier aber eine Frage zu Assembler habe dachte ich das gehört in dieses Forum.
Ich weiß dass die Schreibweise in GNU C++ und Visual C++ unterschiedlich ist aber nagut ...
Hier ist mein Code:
asm // In GNU C++ sieht das so aus ( " push %ecx \n" " push %ebx \n" " push %ax \n" " mov %ecx, len \n" " mov %ebx, buf \n" "label1: \n" " mov %al,[%ebx+0] \n" // Fehler meldung: "invalid cahr '[' beginning operand 2 `[%ebx+0]'" " mov %ah,[%ebx+2] \n" // Fehler meldung: "invalid cahr '[' beginning operand 2 `[%ebx+2]'" " mov [%ebx+2],%al \n" // Fehler meldung: "invalid cahr '[' beginning operand 1 `[%ebx+2]'" " mov [%ebx+0],%ah \n" // Fehler meldung: "invalid cahr '[' beginning operand 1 `[%ebx+0]'" " add %ebx,3 \n" " dec %ecx \n" " jnz label1 \n" " pop %ax \n" " pop %ebx \n" " pop %ecx \n" );Könnt ihr mir sagen was daran falsch ist?
Oder sollte ich das doch lieber im C++ Forum fragen?
-
LukasBanana schrieb:
Oder sollte ich das doch lieber im C++ Forum fragen?
Nein. Und Doppelpost werden nicht gerne gesehen.
LukasBanana schrieb:
Hallo,
ich habe zum ersten mal was mit Assembler gemacht bzw. versuche zu machen und es geht natürlich erst mal schief ^^
Also ich will mit Assembler erst mal nur was mit meinem GNU C++ Compiler machen. Also Assembler in ein C++ Programm einbauen. Da ich hier aber eine Frage zu Assembler habe dachte ich das gehört in dieses Forum.
Ich weiß dass die Schreibweise in GNU C++ und Visual C++ unterschiedlich ist aber nagut ...
Hier ist mein Code:
asm // In GNU C++ sieht das so aus ( " push %ecx \n" " push %ebx \n" " push %ax \n" " mov %ecx, len \n" " mov %ebx, buf \n" "label1: \n" " mov %al,[%ebx+0] \n" // Fehler meldung: "invalid cahr '[' beginning operand 2 `[%ebx+0]'" " mov %ah,[%ebx+2] \n" // Fehler meldung: "invalid cahr '[' beginning operand 2 `[%ebx+2]'" " mov [%ebx+2],%al \n" // Fehler meldung: "invalid cahr '[' beginning operand 1 `[%ebx+2]'" " mov [%ebx+0],%ah \n" // Fehler meldung: "invalid cahr '[' beginning operand 1 `[%ebx+0]'" " add %ebx,3 \n" " dec %ecx \n" " jnz label1 \n" " pop %ax \n" " pop %ebx \n" " pop %ecx \n" );Könnt ihr mir sagen was daran falsch ist?
Einiges. Zwar gibt es Unterschiede in der Syntax zwischen etwa Visual C++ und g++ - die sind aber letztlich unerheblich. Entscheidend sind die semantischen Unterschiede:
in Visual C++ ist der Assembler eingebettet in die Sprache, man hat innerhalb des Assemblercodes prinzipiell die Möglichkeit, auf alle Bezeichner des Hochsprachencodes direkt zuzugreifen.
Bei g++ ist der Assembler dagegen Teil des back-ends - man hat somit grundsätzlich keine Zugriff auf Teile der Hochsprache. Da der Code, so wie er geschrieben wird (bis auf Argumentsubstitution) im Assembleroutput erscheint, besteht hier kein Unterschied zwischen der Einbettung des Codes mittels Inline-Assembler oder der Verwendung eines externen Assemblers. Gleichzeitig macht die Möglichkeit der Argumentsubstition (in Form von Constraints) diesen Assembler erheblich mächtiger als es der Inline-Assembler von Visual C++ (der übrigens nicht für 64-bit Targets verwendet werden kann) jemals sein könnte. Es dürfte allerdings für den Anfänger schwieriger zu erlernen sein.
Willst du Assemblerprogrammierung lernen, ist die Verwendung eines stand-alone Assemblers imo immer zu empfehlen. Das muss nicht bedeuten, dass das gesamte Programm in asm geschrieben werden muss. Die notwendigen Deklarationen, um eine C-kompatible Funktion zu definieren und von C aus aufzurufen, kann man sich in der Regel leicht aneignen.void flipBufferASM(char* buf, int len) { asm ( "leal (%1,%1,2), %1 \n" "addl %1, %0 \n" "negl %1 \n" "1: \n" "add $3, %1 \n" "movb -3(%0,%1), %%al \n" "movb -1(%0,%1), %%ah \n" "movb %%al, 2(%0) \n" "movb %%ah, 0(%0) \n" "jnz 1b \n" :: "r"(buf), "r"(len) : "eax" ); }
-
Danke schon mal
jetzt kompiliert er das auch.
Allerdings kenne ich mich mit Assembler noch viel zu wenig aus und die Funktion macht nicht das was sie machen soll?! Daher poste ich einfach mal den Code den ich ersatz Weise die ganze Zeit in C++ geschrieben hatte:void flipBufferCPP(char* buf, u32 len) { register char tmp; for (register u32 i = 0; i < len; i += 3) { tmp = buf[i]; buf[i] = buf[i+2]; buf[i+2] = tmp; } }Die ASM Funktion die du mir gepostet hast kann kompiliert werden aber aus irgend einem Grund macht sie nicht das selbe wie diese Funktion
-
Entsprechend deinem eigenen Assemblerversuch bin ich davon ausgegangen, dass len die Anzahl der Datenelemente ist und nicht die Anzahl der bytes. Dementsprechend wird dieser Wert bei mir als Erstes verdreifacht. Du müsstest also die erste Zeile meines Codes entfernen. Bei den letzten beiden Zahlen stimmt das Offset nicht. Statt 2 und 0 muss es, wie in den Zeilen darüber natürlich -3 bzw. -1 sein. Ich sollte erwähnen, dass diese Umsetzung relativ primitiv ist, und wahrscheinlich nicht zu optimaler Performance führt.
-
ich versteh das nicht: es funktioniert immer noch

Es kompiliert zwar aber die Funktion verändert anscheinend meien buf pointer nicht bzw. deren Elemente.PS: Warum soll das nicht optimieren? Jedenfalls schneller als C++, oder?!
-
also ich würde behaupten, dass ein c-Kompiler die schleife bessser umsetzt, als du es in assembler schaffst.
Acuh sollte man das schlüsselwort "register" nicht benutzen, der Kompiler kriegt schon selbst mit, welche variablen er besser in registern halten sollte und welche nicht.
Ich glaube gehört zu haben, dass das register schlüsselwort sowiso ignoriert wird, wenn die Codeoptimierung eingeschaltet ist.
-
In meiner IDE ist glaube ich die Optimierung komplett ausgeschaltet. Ich hab mal die höchste Optimierungsstufe ausprobiert aber dann lief das Programm überhaupt nicht mehr XD
Bis zu welcher Stufe ist das denn sinnvoll und ratsam?
-
LukasBanana schrieb:
Ich hab mal die höchste Optimierungsstufe ausprobiert aber dann lief das Programm überhaupt nicht mehr XD
Dann ist das Programm falsch.
-
LukasBanana schrieb:
In meiner IDE ist glaube ich die Optimierung komplett ausgeschaltet. Ich hab mal die höchste Optimierungsstufe ausprobiert aber dann lief das Programm überhaupt nicht mehr XD
Bis zu welcher Stufe ist das denn sinnvoll und ratsam?ratsam ist das problem zu finden und zu fixen. dann kannst du vermutlich alle optimierungen einschalten.
PS: Warum soll das nicht optimieren? Jedenfalls schneller als C++, oder?!
warum sollte jemand der es nicht hinbekommt alleine seinen assemblercode compiliert zu bekommen einen besseren code generieren als ein jahrelang optimierter compiler, der von unmengen an experten geschrieben wurde?
-
rapso schrieb:
PS: Warum soll das nicht optimieren? Jedenfalls schneller als C++, oder?!
warum sollte jemand der es nicht hinbekommt alleine seinen assemblercode compiliert zu bekommen einen besseren code generieren als ein jahrelang optimierter compiler, der von unmengen an experten geschrieben wurde?
Das ist eine Gegenfrage aber kein Argument.
Ich denke schon auch dass die for Schleife in C++ sehr schnell ist. Aber allein eine 'Schleife' mit einem hässlichen "goto" ist schneller

Hat mich auch etwas verwundert aber schaut euch mal folgenden Vergleich an:// Schnell for (int i = 0; i < 100; ++i) { printf("%i", i); } // Schneller int i = 0; loop: { printf("%i", i); } if (++i < 100) goto loop;Und ich denke das eine Schleife in Assembler geschrieben noch schneller ist.
Das steht auch in einem Tutorial das ich gelesen habe. Daher hab ich nämlich die Schleife
-
LukasBanana schrieb:
rapso schrieb:
PS: Warum soll das nicht optimieren? Jedenfalls schneller als C++, oder?!
warum sollte jemand der es nicht hinbekommt alleine seinen assemblercode compiliert zu bekommen einen besseren code generieren als ein jahrelang optimierter compiler, der von unmengen an experten geschrieben wurde?
Das ist eine Gegenfrage aber kein Argument.
eine gegenfrage die dir nach einer sekunde drueber nachdenken die antwort geliefert haette.
LukasBanana schrieb:
Ich denke schon auch dass die for Schleife in C++ sehr schnell ist. Aber allein eine 'Schleife' mit einem hässlichen "goto" ist schneller

...1. vermutlich hast du hier auch keine compiler optimierungen angehabt

2. 99.999% der zeit geht vermutlich im print drauf... das zeigt zudem, dass du nichtmal ordentlich performance testen kannst.tut mir leid, aber du setzt am falschen ende an. fixe deinen code sodass er mit allen kompiler optimierungen funktioniert, davon hast du wirklich viel viel mehr.
Und ich denke das eine Schleife in Assembler geschrieben noch schneller ist.
Das steht auch in einem Tutorial das ich gelesen habe. Daher hab ich nämlich die Schleifeassemblercode ist so gut wie die person die den schreibt. ein mensch ist inteligenter als ein compiler -> generel gesprochen ist somit assembler potentiell schneller als der vom c++ compiler.
andersrum: ein mensch kann besser von deutsch nach spanisch uebersetzen als das z.b. bablefish.altavista.com machen kann.-> generel gesprochen ist somit menschlich uebersetztes spanish besser als vom "sprach compiler".ich wuerde trotzdem eher auf babelfish setzen als auf deine faehigkeiten auf spanisch zu uebersetzen. so ist das auch beim assembler/opcode generieren.
nochmals: fixe deinen code dass er mit allen optimierungen funktioniert, dann kann es durchaus sein dass er ploetzlich 10mal schneller laeuft, vermutlich auch viel schneller als er waere wenn du alles per hand in assembler schreiben wuerdest. wenn du assembler lernen willst, mach das, ich rate dir nicht davon ab ;), aber mit dem ersten versuch kannst du nicht erwarten irgendwas genial schnelles zu machen :p