-         

Seite 1 von 2 12 LetzteLetzte
Ergebnis 1 bis 10 von 14

Thema: Problem mit Bitverschiebung

  1. #1
    Erfahrener Benutzer Roboter-Spezialist
    Registriert seit
    31.08.2005
    Ort
    bei Graz
    Alter
    27
    Beiträge
    225

    Problem mit Bitverschiebung

    Anzeige

    Hallo,
    muss gerade viel mit Bitverschiebungen arbeiten und habe hier ein Riesenproblem:

    Hier mal der Code des ganzen

    Code:
    uint32_t i=0;
    uint32_t t;
      
    for(i=0; i<20; i++)
    {
      t = 1<<i;
    }
    Ansich nichts kompliziertes, is auch nur ein Beispiel für mein Problem.

    Wenn ich das ganze nun mit dem GCC von WinAvr kompiliere (keine Warnings, Fehler, ect) kann ich im Debugfenster von AVR Studio folgende Werte ablesen:

    Code:
    1
    2
    4
    8
    16
    32
    64
    128
    256
    512
    1024
    2048
    4096
    8192
    16384
    -->4294934528
    Wie sich der aufmerksame Leser vielleicht vorstellen kann stimmt der letzte Wert nicht.
    Eine Bitverschiebung um 1 nach links sollte doch gleich wirken wie eine multiplikation mit 2.

    Zig mal mit Taschenrechner, und PC-C Programmen probiert, da klappts immer.

    Die Frage ist nun:
    Hat der Compiler einen Fehler?
    Stimmt etwas in den Headerdateien nicht (hab eigentlich nachgeschaut)
    Habe ich eine Fehler im Code?
    Muss ich um mit uint32_t Typen zu arbeiten ein besonderes Compilerflag setzen?



    Ich bitte um Antwort!

    lg MoFe

  2. #2
    Neuer Benutzer Öfters hier
    Registriert seit
    28.01.2008
    Alter
    24
    Beiträge
    7
    Ich habe gerade einfach mal unter Linux diesen Code compiliert und ausgeführt:
    Code:
    #include <stdio.h>
    
    int main(void)
    {
    	unsigned long i=0;
    	unsigned long t;
    	for(i=0;i<20;i++)
    	{
    		t= 1<<i;
    		printf("%u \n", t);
    	}
    	return 0;
    }
    und ich erhielt die Ausgabe
    Code:
    1
    2
    4
    8
    16
    32
    64
    128
    256
    512
    1024
    2048
    4096
    8192
    16384
    32768
    65536
    131072
    262144
    524288
    also kann es an deinem Programmcode eigentlich nicht liegen. Allerdings wundert mich dein Ergebnis auch, denn du hast als letztes Ergebnis genau den maximalen Wert den die Variable annehmen kann minus den erwarteten Wert.
    Ich kann aber auch nicht sagen woran das liegen könnte. Vielleicht ein Fehler im AVR-Studio?
    Aber eine andere Möglichkeit weiß ich auch nicht.

  3. #3
    Super-Moderator Robotik Visionär Avatar von PicNick
    Registriert seit
    23.11.2004
    Ort
    Wien
    Beiträge
    6.836
    Na, der Effekt is klar:
    Der nächste Shift setzt das Vorzeichen von einem 16-Bit-Wort.
    Da es aber 32-Bit sein sollen, kopiert er das Bit in alle andern darüber.
    Raus kommt eben 0xfff800 = 4294934528
    Eben wir bei einem
    int32_variable = int16_variable.

    Ich hätt ja den Printf im Verdacht, der kann es machmal.

    Versuch mal

    printf("%u \n", (t & (1<<i));

    sieht blöd aus, könnt aber helfen
    mfg robert
    Wer glaubt zu wissen, muß wissen, er glaubt.

  4. #4
    Erfahrener Benutzer Fleißiges Mitglied
    Registriert seit
    06.02.2007
    Beiträge
    139
    Hallo

    Da sich wohl alles auf einem uProzessor abspielt gibt es wohl kein printf in dem sinne, ich schätze die werte kommen aus dem Debugger und entsprechen den Tatsächlichen Werten.

    Vermutlich kann der ka 8bit prozessor nur 16bit variablen verarbeiten...

    lg manhunt

  5. #5
    Erfahrener Benutzer Robotik Einstein Avatar von Felix G
    Registriert seit
    29.06.2004
    Ort
    49°32'N 8°40'E
    Alter
    34
    Beiträge
    1.780
    Vermutlich kann der ka 8bit prozessor nur 16bit variablen verarbeiten...
    Daran ist dann aber in diesem Fall nicht der Controller schuld sondern der C-Compiler, der die Anweisung nicht korrekt in Assembler-Befehle umsetzt. Denn prinzipiell kann auch ein 8-Bit Controller nahezu beliebig große Zahlen addieren, sofern man ihn richtig programmiert.


    Ich würde also erstmal einen Blick auf den erzeugten Assembler-Code werfen, um herauszufinden was der Compiler da falsch macht. (und die shift-Funktion ggf. als inline-Assembler selbst schreiben)
    So viele Treppen und so wenig Zeit!

  6. #6
    Erfahrener Benutzer Roboter-Spezialist
    Registriert seit
    31.08.2005
    Ort
    bei Graz
    Alter
    27
    Beiträge
    225
    Hallo,
    bin leider des Assemblercodens nicht mächtig
    Könntest du mir einen Code dafür posten?

    Mir läuft die Zeit etwas davon
    Werde trotzdem mal probieren den Assemblierten Code zu verstehen. . .

    lg MoFe

  7. #7
    Super-Moderator Robotik Visionär Avatar von PicNick
    Registriert seit
    23.11.2004
    Ort
    Wien
    Beiträge
    6.836
    Na, dann, bevor du im Assembler verschwindest:
    Code:
      
    for(i=0; i<20; i++) 
    { 
      t = 1<<i; 
      t &= (1<<i);  // das zerschmettert alle ungewollten Bits. 
    }
    mfg robert
    Wer glaubt zu wissen, muß wissen, er glaubt.

  8. #8
    Erfahrener Benutzer Roboter-Spezialist
    Registriert seit
    31.08.2005
    Ort
    bei Graz
    Alter
    27
    Beiträge
    225
    Hallo PickNick,
    irgendwie finde ich den unterschied zwischen deinem und meinem Code nicht, außer die UND Verknüpfung deren Sinn ich nicht sehe :/

    Ergebnis ist bei mir genau das gleiche


    Hier mal der Inline Assembler:
    Code:
    0000011E:   93CF        PUSH    R28              Push register on stack
    +0000011F:   93DF        PUSH    R29              Push register on stack
    +00000120:   B7CD        IN      R28,0x3D         In from I/O location
    +00000121:   B7DE        IN      R29,0x3E         In from I/O location
    +00000122:   9728        SBIW    R28,0x08         Subtract immediate from word
    +00000123:   B60F        IN      R0,0x3F          In from I/O location
    +00000124:   94F8        CLI                      Global Interrupt Disable
    +00000125:   BFDE        OUT     0x3E,R29         Out to I/O location
    +00000126:   BE0F        OUT     0x3F,R0          Out to I/O location
    +00000127:   BFCD        OUT     0x3D,R28         Out to I/O location
    47:         uint32_t i=0, t;
    +00000128:   821D        STD     Y+5,R1           Store indirect with displacement
    +00000129:   821E        STD     Y+6,R1           Store indirect with displacement
    +0000012A:   821F        STD     Y+7,R1           Store indirect with displacement
    +0000012B:   8618        STD     Y+8,R1           Store indirect with displacement
    52:         for(i=0; i<20; i++)
    +0000012C:   821D        STD     Y+5,R1           Store indirect with displacement
    +0000012D:   821E        STD     Y+6,R1           Store indirect with displacement
    +0000012E:   821F        STD     Y+7,R1           Store indirect with displacement
    +0000012F:   8618        STD     Y+8,R1           Store indirect with displacement
    +00000130:   C01D        RJMP    PC+0x001E        Relative jump
    54:           t = 1<<i;
    
    Hier fängs an:
    
    +00000131:   812D        LDD     R18,Y+5          Load indirect with displacement
    +00000132:   813E        LDD     R19,Y+6          Load indirect with displacement
    +00000133:   E081        LDI     R24,0x01         Load immediate
    +00000134:   E090        LDI     R25,0x00         Load immediate
    +00000135:   2E02        MOV     R0,R18           Copy register
    +00000136:   C002        RJMP    PC+0x0003        Relative jump
    +00000137:   0F88        LSL     R24              Logical Shift Left
    +00000138:   1F99        ROL     R25              Rotate Left Through Carry
    +00000139:   940A        DEC     R0               Decrement
    +0000013A:   F7E2        BRPL    PC-0x03          Branch if plus
    +0000013B:   27AA        CLR     R26              Clear Register
    +0000013C:   FD97        SBRC    R25,7            Skip if bit in register cleared
    +0000013D:   95A0        COM     R26              One's complement
    +0000013E:   2FBA        MOV     R27,R26          Copy register
    +0000013F:   8389        STD     Y+1,R24          Store indirect with displacement
    +00000140:   839A        STD     Y+2,R25          Store indirect with displacement
    +00000141:   83AB        STD     Y+3,R26          Store indirect with displacement
    +00000142:   83BC        STD     Y+4,R27          Store indirect with displacement
    +00000143:   818D        LDD     R24,Y+5          Load indirect with displacement
    +00000144:   819E        LDD     R25,Y+6          Load indirect with displacement
    +00000145:   81AF        LDD     R26,Y+7          Load indirect with displacement
    +00000146:   85B8        LDD     R27,Y+8          Load indirect with displacement
    +00000147:   9601        ADIW    R24,0x01         Add immediate to word
    +00000148:   1DA1        ADC     R26,R1           Add with carry
    +00000149:   1DB1        ADC     R27,R1           Add with carry
    +0000014A:   838D        STD     Y+5,R24          Store indirect with displacement
    +0000014B:   839E        STD     Y+6,R25          Store indirect with displacement
    +0000014C:   83AF        STD     Y+7,R26          Store indirect with displacement
    +0000014D:   87B8        STD     Y+8,R27          Store indirect with displacement
    +0000014E:   818D        LDD     R24,Y+5          Load indirect with displacement
    +0000014F:   819E        LDD     R25,Y+6          Load indirect with displacement
    ---- No Source ------------------------------------------------------------------------------------
    +00000150:   81AF        LDD     R26,Y+7          Load indirect with displacement
    +00000151:   85B8        LDD     R27,Y+8          Load indirect with displacement
    +00000152:   3184        CPI     R24,0x14         Compare with immediate
    +00000153:   0591        CPC     R25,R1           Compare with carry
    +00000154:   05A1        CPC     R26,R1           Compare with carry
    +00000155:   05B1        CPC     R27,R1           Compare with carry
    +00000156:   F2D0        BRCS    PC-0x25          Branch if carry set
    ich glaube das das Problem bei Speicherstelle +00000131 und folgenden liegt. Hier werden Y+5 und Y+6 in R18 und R19 kopiert. Das sind aber nur 2 byte, meine uint32_t Variablen haben ja 4 .
    Gleiches geschieht an Stelle +00000133 wo R24 und R5 beschrieben werden, nicht jedoch R26 und R27.

    Kann eigentlich kein Assembler, aber liege ich richtig in der Annahme das hier der Fehler liegt?

    lg MoFe

  9. #9
    Super-Moderator Robotik Visionär Avatar von PicNick
    Registriert seit
    23.11.2004
    Ort
    Wien
    Beiträge
    6.836
    das AND ist zum ausmaskieren der unwerwünschten Bits
    Andere Idee:
    Versuch mal mit casten
    t = (uint32)(1<<i);


    EDIT: Denke, du hast in etwa recht. Versuch das Casten wirklich mal
    mfg robert
    Wer glaubt zu wissen, muß wissen, er glaubt.

  10. #10
    Erfahrener Benutzer Roboter-Spezialist
    Registriert seit
    31.08.2005
    Ort
    bei Graz
    Alter
    27
    Beiträge
    225
    Hallo,
    wenn der Fehler in der Bitverschiebung liegt, was er auch tut ( ) hilft es mir nichts den falschen Wert mit dem gleichen falschen Wert zu maskieren.

    Leider funktionierts mit casten auch nicht

    inline assembler wird wohl die einzige Lösung sein, aber ich schaffe es nicht mal diesen asm code auf inline assembler zu portieren. . .

    lg MoFe

Seite 1 von 2 12 LetzteLetzte

Berechtigungen

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