- LiFePO4 Speicher Test         
Seite 1 von 2 12 LetzteLetzte
Ergebnis 1 bis 10 von 16

Thema: NOP in "C"

Hybrid-Darstellung

Vorheriger Beitrag Vorheriger Beitrag   Nächster Beitrag Nächster Beitrag
  1. #1
    Erfahrener Benutzer Roboter Genie
    Registriert seit
    05.11.2007
    Beiträge
    1.076

    NOP in "C"

    Hallo zusammen,
    ich wollte in meinen "C"-Code einen Assembler Befehl NOP einbauen.

    MPLAB C-Compiler 8.87
    ------------------------------------
    Das der C-Compiler mit dem Befehl NOP nichts anfangen kann leuchtet mir ein

    NOP;

    deshalb kam auch die Fehlermeldung:
    410.1 undefined identifier "NOP"
    ------------------------------------
    also habe ich es entsprechend declariert

    #define NOP asm("NOP");

    NOP;

    Doch nun bekam ich folgende Meldung:

    405.23 redefining preprocessor macro "NOP"

    --------------------------------------------
    Nach einigem Suchen habe ich dann die "Definierte Declaration" von NOP gefunden.
    Da hat man doch tatsächlich den NOP wie folgt declariert:
    Code:
    #pragma intrinsic(_nop)
    extern void _nop(void);
    #define NOP() _nop()
    Warum macht man denn so etwas ? Was sollen da die Klammern, das ist doch keine Funktion, das sieht für mich aus wie ein CALL .....

    Wenn ich also in meinem "C" Programm schreibe:
    NOP();
    dann funktioniert es nun auch. Aber wo liegt da der Sinn ?

    mfg. Siro

  2. #2
    Moderator Robotik Visionär Avatar von radbruch
    Registriert seit
    27.12.2006
    Ort
    Stuttgart
    Alter
    62
    Beiträge
    5.799
    Blog-Einträge
    8
    Hallo

    In der RP6-Library wird nop() so definiert:
    Code:
    // Assembly and system macros:
    #define nop(); {__asm__ volatile("nop\n\t");}
    (Aus RP6M256.h)

    Was das aber bedeutet weiß ich auch nicht. Vermutlich wird so in den Programmablauf eine Zeile Assembler eingefügt bevor die Hex-Datei erzeugt wird.

    Gruß

    mic
    Bild hier  
    Atmel’s products are not intended, authorized, or warranted for use
    as components in applications intended to support or sustain life!

  3. #3
    Erfahrener Benutzer Roboter Genie
    Registriert seit
    05.11.2007
    Beiträge
    1.076
    Hallo mic, also dort auch mit den Klammern, so muss man also in "C" nun auch
    nop();
    schreiben, was aussieht wie ein Unterprogramm Aufruf ohne Parameter.

    man hätte doch auch:
    #define nop; {__asm__ volatile("nop\n\t");}
    declarieren können, dann würde man in "C" nur
    nop;
    schreiben müssen, was meiner Meinung nach wesentlich sinnvoller bzw. übersichtlicher ist, da ja hier direkt, wie Du schon richtig sagtest, eine Assemblerzeile eingefügt wird und nix aufgerufen wird.
    Das ist für eine Vortäuschung falscher Tatsachen, weil ich würde im Assemblelisting einen "CALL" suchen und durch die Schreibweise eine zusätzliche Stackbelastung vermuten.
    Ist ja kein Weltuntergang, aber ich find das eher verwirrend und der Sinn ist mir bisher verborgen geblieben.

    Siro

  4. #4
    Moderator Robotik Visionär Avatar von radbruch
    Registriert seit
    27.12.2006
    Ort
    Stuttgart
    Alter
    62
    Beiträge
    5.799
    Blog-Einträge
    8
    Hallo

    cli() und sei() sind auch keine Funktionen.

    Das sind die Folgen der großen Freiheiten die man bei C hat.

    mic
    Bild hier  
    Atmel’s products are not intended, authorized, or warranted for use
    as components in applications intended to support or sustain life!

  5. #5
    Erfahrener Benutzer Robotik Einstein
    Registriert seit
    07.03.2011
    Beiträge
    1.899
    Wie man sieht, kommt das mit dem nop() öfter vor. Bei den PICs kenne ich das von HI-TECH und vom GCC. Beim RP6 schein das ja so zu sein. Eine wirklich Erklärung habe ich nicht, ich vermute, das man den Namespace der Variablen nicht mit prozessorspezifischen Namen füllen will.

    Zitat Zitat von Siro Beitrag anzeigen
    Das ist für eine Vortäuschung falscher Tatsachen, weil ich würde im Assemblelisting einen "CALL" suchen und durch die Schreibweise eine zusätzliche Stackbelastung vermuten.
    Auch wenn ab und an das Gegenteil behauptet wird, C ist eine Hochsprache. Eine C-Funktion ist einen Funktion in C und gehorcht den Regeln von C. Ob daraus ein CALL in Assembler wird, ist nicht gesagt und wird auch in der C-Definition nicht gefordert. Diese zu erwarten ist schlichtweg Unsinn. Der Compiler kann jede Funktion inlinen und es gibt keinen CALL. Er kann umgekehrt bei einem Ausdruck wie float x * float y eine interne "Assemblerfunktion" aufrufen. Gleiches gilt natürlich auch für komplexere Konstrukte wie switches.

    Die meissten C-Programmierer haben noch nie in ihrem Leben ein Assemblerlisting ihres C Codes gesehen. Ob mit ihrem Code ein ARM, MIPS, SPARC PowerPC oder x86 läuft, ist und soll ihnen auch egal sein. Und bei der heutigen Leistungsfähigkeit der µC kann man die dort auch einreihen. So ein klassischer APPLE ][ hatte einen 1 MHz Prozessor und 32 bis 64 kB Speicher für Code und Daten. Auf diesem wurde unter anderem das erste Spreadsheet entwickelt, mit Sicherheit nicht, mit dem Assemblerlisting in der Hand.

    Seitdem ich die PIC16 in C programmiere, hab ich mir die Listings immer seltener angeschaut. Jetzt benutze ich die PIC24, ich hab erst einmal ins Listing geschaut, ich kenne den Assembler garnicht. Den x86 Assembler kenne ich auch nur im 16 Bit Mode, welche Register und welche Befehle er im protected oder 64 Bit mode hat weiß ich nicht. Trotzdem programmiere ich da in jeder Sprache, die mein Problem löst, C eingeschlossen. Und die Vorstellung eines Assemblerlistings eines einige 10 MB großen Programms ...

    Wer in C (C++, C#, Java, PASCAL, PERL, PHP ...) programmiert, muß auch in dieser Sprache sein Problem formulieren, analysieren und lösen. Und ob der Rechner daraus Assemblercode macht oder sich Hilfe aus der Cloud holt, spielt keine Rolle, solange er die Sprachdefinition erfüllt.

    MfG Klebwax
    Strom fließt auch durch krumme Drähte !

  6. #6
    Erfahrener Benutzer Roboter Genie
    Registriert seit
    05.11.2007
    Beiträge
    1.076
    Ich denke einfach generell in Assembler und schaue mir selbst bei Kleinigkeiten an, was der Compiler draus macht.
    Aber Du hast natürlich recht, der Compiler darf anscheinend Unterprogamme als Inline codieren.
    Da war ich ebenso erstaunt, dass der Compiler mal eben meinen Ablaufplan selbst geändert hat. Denn der Code entsprach oftmals nicht mehr meinem Flussdiagramm.
    Das Resultat blieb jedoch erhalten.
    Für mich ist eine Funktion generell ein Stückchen Programmcode welcher mittels call aufgerufen wird. Weil sonst ist das ja keine Funktion mehr.

    Bei cli() und sti() finde ich die "Funktionsklammern" (nennt man die nicht so ?) schon mehr als unnütz.
    Aber das ist sicher Geschmackssache. Ich habe jetzt meine eigenen Assemblerbefehle declariert, das erlaubt ja die Freiheit von "C".

  7. #7
    Erfahrener Benutzer Robotik Einstein
    Registriert seit
    07.03.2011
    Beiträge
    1.899
    Zitat Zitat von Siro Beitrag anzeigen
    Ich denke einfach generell in Assembler und schaue mir selbst bei Kleinigkeiten an, was der Compiler draus macht.
    Dann solltest du konsequenterweise auch in Assembler programmieren.

    Der Compiler macht genau das, was du ihm sagst. Wie er das macht, mußt du ihm überlassen. Wenn du in den Flieger von Frankfurt nach New York steigst, wird er dich (meist) auch dahin bringen. Welchen genauen Kurs er nimt, wieviel Gas er gibt etc. liegt beim Piloten, nicht bei dir. Und wenn du pünktlich in New York bist, hat er seine Aufgabe zur vollsten Zufriedenheit ausgeführt.

    Wenn du in C scheibst:

    a = b + c;

    ist die Aufgabe, in die Variable a die Summe von b und c zu speichern, und nicht den Prozessor eine Addition ausführen zu lassen.

    Findet der Compiler heraus, daß b und c Konstante sind, dann erfüllt er die Aufgabe auch (und sogar effektiver) wenn er Summe gleich selbst berechnet und sie in a speichert. Änliches gilt auch, wenn in a schon die Summe steht.

    Und in C ist es nun einmal so, daß am Anfang einer Anweisung entweder ein reseviertes Wort wie if, while, etc., oder ein Symbol steht. Ist diese Symbol eine Varible, dann muß darauf eine direkte oder indirekte Zuweisung, also ein = oder += oder ein ++ folgen. Folgt das nicht, ist es eine Funktion und da sind Klammern erforderlich.

    Sieht das mal nicht so aus, verbirgt sich dahinter Preprozessor Magic, die je nachdem den Code leichter lesbar macht, oder den Anwender so in die Irre führt, daß er ihn garnicht mehr versteht. Der Compiler selbst sieht das aber nicht.

    MfG Klebwax
    Strom fließt auch durch krumme Drähte !

  8. #8
    Erfahrener Benutzer Robotik Visionär Avatar von oberallgeier
    Registriert seit
    01.09.2007
    Ort
    Oberallgäu
    Beiträge
    8.693
    Zitat Zitat von Siro Beitrag anzeigen
    ... so muss man also in "C" nun auch
    nop();
    schreiben ...
    Funktioniert bei Euch dieses
    Code:
    nop();
    in C? Bei mir wird ein Fehler ausgegeben - egal ob Groß- (wie SEI oder CLI) oder Kleinschreibung. Nur das Format
    Code:
    __asm__ volatile("nop\n\t");
    funktioniert; bei mir aktuell ohne define, da ich es nur einmal benötig(t)e.

    Anmerkung: A.VR Studio 4, Version 4.18, Build 700, mit GCC/WinAVR-20100110; WinXPpro 2002 SP3
    Ciao sagt der JoeamBerg

  9. #9
    Erfahrener Benutzer Roboter Genie
    Registriert seit
    05.11.2007
    Beiträge
    1.076
    ich vermute, daß in deinem Programmcode

    #include <intrinsics.h>

    fehlt, könnte das sein ?

    Siro

    wenn nicht: welche Fehlermeldung bekommst du genau ?
    Geändert von Siro (02.10.2013 um 15:56 Uhr)

  10. #10
    Erfahrener Benutzer Robotik Einstein
    Registriert seit
    27.08.2013
    Ort
    Region Basel
    Alter
    67
    Beiträge
    2.435
    Hallo Siro,

    1. Wie du erkannt hast darf ein Compiler einen Funktion auch inline generieren. Es gibt dafür sogar das Schlüsselwort inline in Manchen C-Compilern und in C++.

    2. In ANSI-C wurde definiert, dass compiler- und prozessorspezifische Erweiterungen, welche nicht Bestandteil von ANSI-C sind, mit einem, oder zwei, _ anfangen. Dies gilt auch für entsprechende Variablen und Konstanten.
    Damit ist recht schnell ersichtlich, wenn solche Erweiterungen in einem Programm verwendet werden.
    Das wird wichtig, wenn man Code portieren will, bzw. wenn der selbe Code auf unterschiedlichen Prozessoren laufen soll (kommt bei mir öfters vor, besonders bei Übertragungsprotokollen. Wenn man nur ein Code-Modul zu pflegen hat, wird das Leben einfacher).

    3. Grundsätzlich ist nop(); eine Funktion ohne Parameter. NOP ist eine Spezialfall, da es der einzige Maschinenbefehl ist, welcher ausser dem Verbrauch von CPU-Takten keinerlei Wirkung hat. Alle anderen Maschinenbefehle haben irgendwelche Effekte und benötigen teilweise auch Parameter. Für nop(); hat man jetzt nicht extra einen syntaktischen Sonderfall einführen wollen. Es wäre auch eine CPU denkbar, welche als Parameter von nop(); die Anzahl CPU-Takte übernimmt, welche "verbraten" werden sollen.

    4. Dass dein Ablauf und der vom Compiler erzeugte nicht ganz übereinstimmen ist normal, für optimierende Compiler!
    Der stellt dir auch mal Schleifen um oder rollt sie auf. Die Programmlogik bleibt dabei aber erhalten. Bei den meisten CPUs versucht der Compiler auch Speicher- und IO-Zugriffe zu optimieren, d.h. nur einmal darauf zuzugreifen und dann mit einer Kopie im Register zu arbeiten, was meist schneller ist.
    Das kann natürlich besonders bei IO-Ports in die Hose gehen

    while (IO_bit)
    ;

    Wenn hier der der Compiler entdeckt, dass IO-bit in der Schleife nicht verändert wird, arbeitet er mit eine Kopie
    Deshalb gibt es das Schlüsselwort volatile, dann weiss der Compiler, dass er bei jeder Verwendung von IO_bit auch auf das entsprechende Port zugreifen muss.
    Man kann aber die Optimierung auch ganz abschalten, dann entspricht der Code mehr deinen Erwartungen, wird aber grösser und langsamer.

    MfG Peter(TOO)

Seite 1 von 2 12 LetzteLetzte

Ähnliche Themen

  1. "RS232-Kabel" oder "USB-ISP-Kabel" zum Programmieren des RN-Control 1.4
    Von Soeren7 im Forum Schaltungen und Boards der Projektseite Mikrocontroller-Elektronik.de
    Antworten: 14
    Letzter Beitrag: 25.07.2012, 15:54
  2. Antworten: 2
    Letzter Beitrag: 15.06.2011, 22:18
  3. LPC1114 (Cortex M0): "sei()" und "cli()"
    Von Jaecko im Forum ARM - 32-bit-Mikrocontroller-Architektur
    Antworten: 1
    Letzter Beitrag: 02.07.2010, 13:25
  4. "Soft-Reset?" und "Finger-Interrupt?"
    Von trapperjohn im Forum Asuro
    Antworten: 8
    Letzter Beitrag: 11.06.2008, 00:02
  5. ASM: was machen "swap" und "cbr" genau?
    Von RHS im Forum AVR Hardwarethemen
    Antworten: 3
    Letzter Beitrag: 18.08.2004, 18:16

Berechtigungen

  • Neue Themen erstellen: Nein
  • Themen beantworten: Nein
  • Anhänge hochladen: Nein
  • Beiträge bearbeiten: Nein
  •  

fchao-Sinus-Wechselrichter AliExpress