AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Thema durchsuchen
Ansicht
Themen-Optionen

CRC von C in Delphi übersetze

Ein Thema von ZOD · begonnen am 23. Mär 2023 · letzter Beitrag vom 28. Mär 2023
Antwort Antwort
ZOD

Registriert seit: 6. Mai 2009
97 Beiträge
 
#1

AW: CRC von C in Delphi übersetze

  Alt 23. Mär 2023, 16:00
Ja, faszinierend.

Vor allem, weil einen diese Kommentare beim "Selbstversuch" erst einmal in die Denkschleife schicken ....
  Mit Zitat antworten Zitat
Benutzerbild von sh17
sh17

Registriert seit: 26. Okt 2005
Ort: Radebeul
1.680 Beiträge
 
Delphi 11 Alexandria
 
#2

AW: CRC von C in Delphi übersetze

  Alt 24. Mär 2023, 07:35
Also manchmal ist ChatGPT schon zu gebrauchen, finde ich. Hab letztens eine Funktion optimiert und hab der KI gesagt, sie solle sie mal umschreiben, ohne die Nutzung von PChar und Pointern. Hat er/sie/es fix erledigt. Hätte mich ein paar Minuten mehr gekostet. Kontrolle des Codes geht dann durch mich schneller.
Sven Harazim
--
  Mit Zitat antworten Zitat
ZOD

Registriert seit: 6. Mai 2009
97 Beiträge
 
#3

AW: CRC von C in Delphi übersetze

  Alt 24. Mär 2023, 11:07
eine erste Rückmeldung und Frage zur CRC Funktion:

das übergebene Funktionsargument pin ist nach meinem Verständnis ein Byte.
Es wird im Folgenden als Pointer auf das erste Zeichen der zu behandelnden Zeichenkette mit Länge len (2. Argument) verwendet.
Ich habe dies gefunden:
http://delphibasics.co.uk/RTL.php?Name=PAnsiChar

Um die CRC Funktion aufzurufen, verwende ich zum Test folgende Funktion:

Delphi-Quellcode:
function ErzeugeSolarisCRCWord(Text: string): word;
var
  tmpAnsiString: AnsiString;

  tmpPAnsiString: PByte;
  tmpPAnsiChar: PAnsiChar;

  tmpLength: Byte;

  tmpTextLength,
    i : integer;

begin
  // initialisieren
  result := 0;
  tmpTextLength := Length(Text);

  // validieren
  if ((tmpTextLength = 0) or (tmpTextLength > 256)) then
    exit;

  // Merker setzen
  tmpAnsiString := Text;
  i := 1;
  tmpPAnsiString := Addr(tmpAnsiString);
  tmpPAnsiChar := Addr(tmpAnsiString[i]);
  tmpLength := Length(tmpAnsiString);

  // CRC berechnen
  // function cal_crc_half(pin: PByte; len: Byte): Word;
  result := cal_crc_half(Addr(tmpPAnsiChar), tmpLength);

end;
Lasse ich das mit Text = 'QPIGS' laufen und setzte einen Haltepunkt vor dem Aufruf von cal_crc_half, habe ich folgende Werte:

Delphi-Quellcode:
  tmpPAnsiString = $12FBD8
  tmpPAnsiChar = 'QPIGS'
  tmpLength := 5

  Addr(tmpPAnsiChar) = $12FBD0
In der Funkton cal_crc_half ist nach der Zuweisung ptr := pin; der Wert von
Delphi-Quellcode:
  ptr = $12FBD0
  ptr^ = 12
Meinem bisherigen Verständnis nach sollte jedoch der derefernierte Wert von ptr ASCII-Wert des ersten Buchstaben von Text bzw. von tmpPAnsiChar sein - also "Q = ASCII 81". ptr^ liefert jedoch 12.

Ich verstehe das nicht, wahrscheinlich weil ich das Thema Pointer, AnsiChar und AnsiString nicht durchblickt habe.

Kann mir jemand helfen?
  Mit Zitat antworten Zitat
Benutzerbild von sh17
sh17

Registriert seit: 26. Okt 2005
Ort: Radebeul
1.680 Beiträge
 
Delphi 11 Alexandria
 
#4

AW: CRC von C in Delphi übersetze

  Alt 24. Mär 2023, 11:37
tmpPAnsiChar ist doch schon ein Pointer, Du übergibts also, denke ich, die Adresse auf die Adresse Addr(tmpPAnsiChar)
Sven Harazim
--
  Mit Zitat antworten Zitat
ZOD

Registriert seit: 6. Mai 2009
97 Beiträge
 
#5

AW: CRC von C in Delphi übersetze

  Alt 24. Mär 2023, 11:50
mhm - das ist sicher richtig. Jedoch bekomme ich ohne Addr() diese Fehlermeldung beim Kompilieren:

[Fehler] uCRCSolaris.pas(174): Inkompatible Typen: 'Char' und 'Byte'

Wie gesagt, ich bin beim Thema Pointer und Adressen sehr unerfahren.
  Mit Zitat antworten Zitat
ZOD

Registriert seit: 6. Mai 2009
97 Beiträge
 
#6

AW: CRC von C in Delphi übersetze

  Alt 24. Mär 2023, 12:19
weiter probiert und mit PByte() kann ich ohne Fehler kompilieren.
So sieht die Aufruffunktion jetzt aus:

Delphi-Quellcode:
function ErzeugeSolarisCRCWord(Text: string): word;
var
  tmpAnsiString: AnsiString;

  tmpPAnsiCharByte,
  tmpPAnsiString: PByte;
  tmpPAnsiChar: PAnsiChar;

  tmpLength: Byte;

  tmpTextLength,
    i : integer;

begin
  // initialisieren
  result := 0;
  tmpTextLength := Length(Text);

  // validieren
  if ((tmpTextLength = 0) or (tmpTextLength > 256)) then
    exit;

  // Merker setzen
  tmpAnsiString := Erzeuge8BitCharString(Text);
  i := 1;
  tmpPAnsiString := Addr(tmpAnsiString);
  tmpPAnsiChar := Addr(tmpAnsiString[i]);
  tmpLength := Length(tmpAnsiString);

  tmpPAnsiCharByte := PByte(tmpPAnsiChar);

  // CRC berechnen
  // function cal_crc_half(pin: PByte; len: Byte): Word;
  result := cal_crc_half(tmpPAnsiCharByte, tmpLength);

end;
Beim Test sind jetzt in function cal_crc_half(pin: PByte; len: Byte): Word; folgende Werte abrufbar (<STRG>+<F7>):

Delphi-Quellcode:
  ptr = $B7980C
  ptr^ = 81
  Char(ptr^) = 'Q'
Ok, soweit läuft das also.

Leider bin ich nun zurück bei meinem Ausgangsproblem - der CRC Berechnung.

Ich erhalte als CRC Wert $D2$36

Laut der Doku der CRC-C-Routine sollte jedoch der CRC für "QPIGS" den Wert $B7$A9 lauten.

Also ist entweder

A - die "Übersetzung C->Delphi" nicht korrekt
B - die Doku falsch
C - oder ich mache noch einen völlig anderen Fehler

Tipps und Hinweise sind ausdrücklich willkommen!
  Mit Zitat antworten Zitat
samso

Registriert seit: 29. Mär 2009
439 Beiträge
 
#7

AW: CRC von C in Delphi übersetze

  Alt 25. Mär 2023, 13:03
Folgendes Programm liefert bei mir das korrekt Ergebnis

Delphi-Quellcode:
program CRCTest;

{$APPTYPE CONSOLE}

{$R *.res}

uses
  SysUtils;

function cal_crc_half(pin: PByte; len: Byte): Word;
var
  crc: Word;
  da: Byte;
  ptr: PByte;
  bCRCHign: Byte;
  bCRCLow: Byte;
const
  crc_ta: array[0..15] of Word = ($0000, $1021, $2042, $3063, $4084, $50a5, $60c6, $70e7,
                                  $8108, $9129, $a14a, $b16b, $c18c, $d1ad, $e1ce, $f1ef);
begin
  ptr := pin;
  crc := 0;
  while (len > 0) do
  begin
    da := crc shr 12; // CRC high four bits
    crc := crc shl 4; // The CRC is shifted to the right by 4 bits, which is equivalent to taking the lower 12 bits of the CRC.
    crc := crc xor crc_ta[da xor (ptr^ shr 4)]; // Add the upper 4 bits of the CRC and the first half of the byte and look up the table to calculate the CRC, then add the remainder of the last CRC.
    da := crc shr 12; // CRC high four bits
    crc := crc shl 4; // The CRC is shifted to the right by 4 bits, which is equivalent to taking the lower 12 bits of the CRC.
    crc := crc xor crc_ta[da xor (ptr^ and $0f)]; // Add the upper 4 bits of the CRC and the last half of the byte and look up the table to calculate the CRC, then add the remainder of the last CRC.
    Inc(ptr);
    Dec(len);
  end;
  bCRCLow := crc and $FF;
  bCRCHign := crc shr 8;
  if (bCRCLow = $28) or (bCRCLow = $0d) or (bCRCLow = $0a) then
    Inc(bCRCLow);
  if (bCRCHign = $28) or (bCRCHign = $0d) or (bCRCHign = $0a) then
    Inc(bCRCHign);
  crc := (bCRCHign shl 8) + bCRCLow;
  Result := crc;
end;

var
  Test: AnsiString;
  CRC: Word;
begin
  try
    Test := 'QPIGS';
    CRC := cal_crc_half(Pointer(Test), Length(Test));
    writeln(IntToHex(CRC, 4));
    ReadLn;
  except
    on E: Exception do
      Writeln(E.ClassName, ': ', E.Message);
  end;
end.
  Mit Zitat antworten Zitat
mytbo

Registriert seit: 8. Jan 2007
479 Beiträge
 
#8

AW: CRC von C in Delphi übersetze

  Alt 25. Mär 2023, 23:10
Tipps und Hinweise sind ausdrücklich willkommen!
Wenn deine Vorgaben vollständig waren, sollte das die Lösung sein:
Delphi-Quellcode:
{$R-}
function CalcCRC(const pmcText: AnsiString): Word;
const
  CRC_TABLE: array[0..15] of Word = (
    $0000, $1021, $2042, $3063, $4084, $50a5, $60c6, $70e7,
    $8108, $9129, $a14a, $b16b, $c18c, $d1ad, $e1ce, $f1ef);
var
  p: PAnsiChar;
  crc: Word;
  tbl: Byte;
  crcLo: Byte;
  crcHi: Byte;
begin
  if pmcText = 'then Exit(0); //=>

  crc := 0;
  p := Pointer(pmcText);
  while p^ <> #0 do
  begin
    tbl := crc shr 12;
    crc := crc shl 4;
    crc := crc xor CRC_TABLE[tbl xor (Ord(p^) shr 4)];
    tbl := crc shr 12;
    crc := crc shl 4;
    crc := crc xor CRC_TABLE[tbl xor (Ord(p^) and $0f)];
    Inc(p);
  end;
  crcLo := crc and $ff;
  crcHi := crc shr 8;
  if (crcLo = $28) or (crcLo = $0d) or (crcLo = $0a) then
    Inc(crcLo);
  if (crcHi = $28) or (crcHi = $0d) or (crcHi = $0a) then
    Inc(crcHi);
  crc := (crcHi shl 8) + crcLo;
  Result := crc;
end;
{$R+}
Die Übersetzung ist nahe am C-Code und bestätigt die Doku:
Delphi-Quellcode:
var
  txt: AnsiString;
begin
  txt := 'QPIGS';
  ShowMessage(CalcCRC(txt).ToHexString(4)); // => $B7A9
Bis bald...
Thomas

Geändert von mytbo (25. Mär 2023 um 23:19 Uhr) Grund: Bereichsprüfung deaktiviert
  Mit Zitat antworten Zitat
Antwort Antwort

 

Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 16:35 Uhr.
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz