Forum: Mikrocontroller und Digitale Elektronik PIC Inline Assembler Problem


von Manuel (Gast)


Lesenswert?

Hallo, ich hoffe ich bin hier richtig... Ich habe folgendes Problem:

Ich bin BA Student, habe gerade eine Praxisphase (soweit noch nicht 
schlimm) und schreibe gerade an einer Funktion, die eine Prüfsumme eine 
UART Kommunikation berechnen soll. Da das ganze einiermaßen schnell sein 
sollte und C keinen Rotate befehl kennt, mein PIC18F452 aber schon 
wollte ich Inline Assembler verwenden:

************************************************************************ 
***

_asm

RRNCF checksum_help_high,1,1    // checksum_help_high 2 Bit 
Rechtsschieben
RRNCF checksum_help_high,1,1

RLNCF checksum_help,1,1         // checksum_help 2 Bit Linksschieben
RLNCF checksum_help,1,1

_endasm

************************************************************************ 
***

Danach geht der C-Code weiter. Das Programm wird anstandslos kompiliert, 
aber die Befehle werden scheinbar nicht ausgeführt, die Variablen sind 
vor und nach dem Inline Assembler Code gleich... Könnt Ihr mir 
vielleicht helfen? Schon mal danke im vorraus

von Severino R. (severino)


Lesenswert?

Du kannst entweder mit einem Debugger (ICD2 oder PICkit2) nachschauen, 
was da passiert, oder Du lässt das Ganze im Simulator laufen.
Vielleicht zuerst mal das Assemblerlisting anschauen, insbesondere ob 
die Parameter checksum_help_high und checksum_help richtig aufgelöst 
werden.
In welcher Bank liegen die Variablen?

von holger (Gast)


Lesenswert?

>Da das ganze einiermaßen schnell sein
>sollte und C keinen Rotate befehl kennt, mein PIC18F452 aber schon
>wollte ich Inline Assembler verwenden:

C kann sehr gut rotieren. Dazu gibt es << oder >>.
Versuch es doch mal damit.

von Severino R. (severino)


Lesenswert?

holger wrote:

> C kann sehr gut rotieren. Dazu gibt es << oder >>.
> Versuch es doch mal damit.

Diese Operatoren rotieren nicht, sie schieben.
Vielleicht spielt das für Manuel keine Rolle, vielleicht aber doch!

von holger (Gast)


Lesenswert?

>Diese Operatoren rotieren nicht, sie schieben.

Ok, schlechtes Beispiel. Er rotiert aber ohne Carry.
Vieleicht ist das sein Problem.

von Severino R. (severino)


Lesenswert?

holger wrote:

> Ok, schlechtes Beispiel. Er rotiert aber ohne Carry.
> Vieleicht ist das sein Problem.

Wenn Du meinst:

Manuel wrote:
> ... die Variablen sind vor und nach dem Inline Assembler Code gleich...

von holger (Gast)


Lesenswert?

>> Ok, schlechtes Beispiel. Er rotiert aber ohne Carry.
>> Vieleicht ist das sein Problem.

>Wenn Du meinst:

Naja, ich habs nicht so mit Assembler.

>Manuel wrote:
>> ... die Variablen sind vor und nach dem Inline Assembler Code gleich...

Aber du hast recht: Das Banking könnte schon ein Problem
sein. Wer weiss was er da ohne Banking rotiert.

Da er ohne Carry rotiert entspricht das doch schieben!?

checksum_help_high=checksum_help_high>>2;
checksum_help=checksum_help<<2;

Da muss er sich um das Banking nicht kümmern.
Das macht der Compiler.

Aber ohne weitere Zusammenhänge zu kennen ist es kaum möglich
weitere (unqualifizierte ;) Aussagen zu machen.

von Manuel (Gast)


Lesenswert?

>C kann sehr gut rotieren. Dazu gibt es << oder >>.
>Versuch es doch mal damit.

">>" rotiert tatsächlich? in meinem C-Buch ist es als shift beschrieben, 
also die Bits werden über den Rand geschoben und sind verloren... 
Rotieren ohne Carry wäre natürlcih traumhaft, das will ich ja.... muss 
ich gleich mal testen...

von Manuel (Gast)


Lesenswert?

<< und >> verlieren leider die Bit, ich bräuchte was, was beim schieben 
Bit 0 in Bit 7 rettet oder umgekehrt... Für mich Rotate ohne Carry, da 
das gerettete Bit ja gleich wieder im Byte ankommt und nicht durch das 
Carrybit geschoben wird... Ich habe mal mein Programm angehägt, 
vielleicht hilft es ja:

/*********************************************************************** 
**********
** Algorithmus zu der Brechnung des Check/Type und Check/Stat Bytes für 
IO-Link  **
**                                        **
** Autor:   Manuel Walz                            **
** Version:   0.1                                **
** Datum:   22.01.2009                              **
**                                        **
************************************************************************ 
*********/

#include <p18f452.h>
#include <stdio.h>

unsigned char Checksum(unsigned char telegram[], unsigned char n);
unsigned char Rotate_Right (unsigned char checksum_help_high);
unsigned char Rotate_Left (unsigned char checksum_help);

void main (void)
{
  unsigned char n = 1;
  unsigned char telegram[4];
  unsigned char ergebniss;

  telegram[0] = 0xA4;
  ergebniss=Checksum(telegram, n);

  //printf("Die Pruefsumme lautet:");
  //printf("%s",Checksum(telegram, n));

  while(1);
}

unsigned char Checksum(unsigned char telegram [],unsigned char n)
{
  unsigned char checksum = 0x52, checksum_help, checksum_help_high;

  while(n != 0)
  {
    n--;
    checksum = checksum^telegram[n];
  }

  checksum_help_high = checksum;

/*********************** Berechnung Low-Half-Byte 
*******************************************/

  checksum_help = (checksum >> 1)^checksum;    // zu ver-XOR-ende Bits 
übereinander schieben
                          // und ver-XOR-en
  checksum    = (checksum_help & 0x01);      // Bit 0 schon korrekt, 
Rest auf Null setzen
  checksum_help >>= 1;              // Bit 1 an richtige Position 
schieben
  checksum    = (checksum_help & 0x02)|checksum;// Bit 1 in Checksum 
einfügen
  checksum_help >>= 1;              // Bit 2 an richtige Position 
schieben
  checksum    = (checksum_help & 0x04)|checksum;// Bit 2 in Checksum 
einfügen
  checksum_help >>= 1;              // Bit 3 an richtige Position 
scheiben
  checksum    = (checksum_help & 0x08)|checksum;// Bit 3 in Checksum 
einfügen


/********************** Berechnung High-Half-Byte 
*******************************************/

  checksum_help = Rotate_Left(checksum_help_high);
  checksum_help_high = Rotate_Right(checksum_help_high);

  checksum_help_high = checksum_help ^ checksum_help_high;  // XOR mit 
ersten 4 Bitpaaren
  checksum_help = (checksum_help_high >> 2);          // Bitpaare in 
richtige Position

  // Positionierte Bitpaare verXOR-en, Bits 4 und 5 maskieren und in 
checksum einfügen
  checksum = ((checksum_help ^ checksum_help_high) & 0x30)| checksum;


  return checksum;
}


unsigned char Rotate_Right (unsigned char checksum_help_high)
{
  _asm  // Inline Assembler Code

  RRNCF checksum_help_high,1,1     // Checksum_help_high 2 Byte nach 
rechts rotieren
  RRNCF checksum_help_high,1,1
  _endasm
  return checksum_help_high;
}

unsigned char Rotate_Left(unsigned char checksum_help)
{
  _asm
  RLNCF checksum_help,1,1        // Checksum_help 2 Byte nach links 
rotieren
  RLNCF checksum_help,1,1
  _endasm
  return checksum_help;
}

von Manuel (Gast)


Lesenswert?

>Du kannst entweder mit einem Debugger (ICD2 oder PICkit2) nachschauen,
>was da passiert, oder Du lässt das Ganze im Simulator laufen.
>Vielleicht zuerst mal das Assemblerlisting anschauen, insbesondere ob
>die Parameter checksum_help_high und checksum_help richtig aufgelöst
>werden.
>In welcher Bank liegen die Variablen?

Ok, das hab ich vor lauter Shift und Rotate übersehen Wie bekomm ich 
denn die Bank raus un ordne sie richtig zu? Im Disassembly scheit es 
nämlich nicht zu stimmen, Da werden, wenn ich das richtig lese, die 
Rotates auf andere Adressen ausgeführt, als die, wo die Variablen 
liegen:

zB funktioniert:

     Checksum_help = ((checksum_help >> 1) ^ checksum;

RRNCF 0xfdf, W, ACCESS  // fdf sollte checksum_help sein

und es funktioniert nicht:

     RLNCF checksum_help,1,0

RLNCF 0xffe, F, ACCESS

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.