byte checksum(byte* chunk, int length) { ...

Moderator: Rockford

Antworten
Benutzeravatar
dl7ukk
Beiträge: 532
Registriert: 25.08.2021 23:03
Has thanked: 69 times
Been thanked: 99 times
Kontaktdaten:

byte checksum(byte* chunk, int length) { ...

Beitrag von dl7ukk »

Hi,

eine Frage an die C .. Programmierer.

Was bedeutet in diesem Befehl
"byte*"(mit Sternchen) und "chunk"

Code: Alles auswählen

// Checksum function from http://www.whizzosoftware.com/sio2arduino/
byte checksum(byte* chunk, int length) {
  int chkSum = 0;
  for(int i=0; i < length; i++) {
    chkSum = ((chkSum+chunk[i])>>8) + ((chkSum+chunk[i])&0xff);
  }
  return (byte)chkSum;
Quelle

Danke

dl7ukk

Benutzeravatar
Kveldulfur
Beiträge: 624
Registriert: 17.08.2021 02:32
Has thanked: 239 times
Been thanked: 163 times
Kontaktdaten:

Re: byte checksum(byte* chunk, int length) { ...

Beitrag von Kveldulfur »

Hallo!

Oh... wie war das noch :-)

Also Du übergibst hier die Variable "chunk" des Typ "byte", jedoch übergibst Du nicht den Wert der Variable, sondern den Zeiger (Speicheradresse).
Änderungen wirken sich somit auch außerhalb der Funktion aus.

In dem Fall scheint der Zeiger auf ein Array von Bytes zu zeigen, wobei "length" angibt wie viele Elemente im Array sind.

Edit: Der Stern hinter Byte erlaubt es Dir direkt auf die Werte von "chunk" zuzugreifen. Der Zeiger wird dereferenziert.

Grüße
Janko

Benutzeravatar
dl7ukk
Beiträge: 532
Registriert: 25.08.2021 23:03
Has thanked: 69 times
Been thanked: 99 times
Kontaktdaten:

Re: byte checksum(byte* chunk, int length) { ...

Beitrag von dl7ukk »

Danke Janko,

daß muß ich noch 100x lesen, bis ich es wirklich verstanden habe ...

Sinn macht es dieser Stelle.


dl7ukk

Erhard
Beiträge: 558
Registriert: 04.11.2021 15:52
Has thanked: 52 times
Been thanked: 111 times
Kontaktdaten:

byte checksum(byte* chunk, int length) { ...

Beitrag von Erhard »

Hi,

das sieht nach einer Routine aus, die entsprechend der Atari-SIO eine Prüfsumme erzeugt.
Es werden einfach alle Bytes der Reihe nach addiert. In Assembler wird der Übertrag glaube ich mit reinaddiert, weiß ich aber nicht mehr genau und müßte ich nachschauen.
Eingentlich würde das Ergebnis bei einem 256-Byte Sektor, wo jedes Byte z.B. $FF ist, ja zu einem mindestens 16-Bit großen Ergebnis für die Prüfsumme führen.
Aber egal wie groß der Datenblock ist, es werden nur die unteren 8 Bits (= 1 Byte) für die Prüfsumme verwendet.

Da die Programmiersprache ACTION! ein wenig ähnelt vermeine ich zu erahnen, wie das abläuft.

Der Routine werden die Adresse übergeben, wo im Speicher sich der Datenblock befindet, über den die Prüfsumme berechnet werden soll sowie dessen Länge.

Als Ergebnis liefert sie 1 Byte zurück, die Prüfsumme eben.

Allerdings würde ACTION! bei dem Konstrukt richtig abkotzen, denn innerhalb der Funktion wird "chksum" als Integer definiert und bei der Rückgabe als Byte.

Innerhalb der Routine wird chksum mit 16 Bits benötigt, damit die Addition von zwei 8-Bit Werten gelingen kann. Vermutlich werden bei

return (byte)chsum;

von dem 16-Bit Wert einfach die oberen 8 weggeschnitten.

Vermutlich funktioniert die Routine nicht mit Datenblöcken von mehr als 256 Bytes, da dann das Ergebnis größer als 16 Bit wird oder werden kann.

Die Atari-SIO kann Datenblöcke bis 64K und bei einigen Cassetten oder bei The!Cart werden auch große Datenblöcke verwendet, wenn auch nicht gerade 64K.

So, alles nur Vermutung und ohne Gewähr.

Beim Schreiben dieses Beitrags wurden keine Tiere verletzt oder getötet.

CU, Erhard

Benutzeravatar
dl7ukk
Beiträge: 532
Registriert: 25.08.2021 23:03
Has thanked: 69 times
Been thanked: 99 times
Kontaktdaten:

Re: byte checksum(byte* chunk, int length) { ...

Beitrag von dl7ukk »

Hi Erhard,
Beim Schreiben dieses Beitrags wurden keine Tiere verletzt oder getötet.
... und ich überlege beim Schreiben was mich heute wieder erwartet. :mrgreen: :mrgreen: :mrgreen:

Aber im Ernst, ja es geht um die Berechnung der Prüfsumme eines Sio-Frames. Die Berechnung der Prüfsumme ist mir soweit klar, hoffe ich.

Alle Bytes des Frames-1 zusammen zählen. (-1, das letzte Byte ist die Prüfsumme). Die Summe, eine 16 Bit-Zahl, in 8+8 Bit zerlegen und die beide 8 Bit-Werte zusammen zählen. Das klappte zumindest, bei den von mir untersuchten Frame immer so.

Die Frame haten 40+1Bytes. Die von mir angeschauten Frame stammen aus der Druckausgabe des Atari-BASIC mit LPRINT oder
OPEN #1,8,0,"P:" : PRINT A$ ... Dann hatte ich bisher nur Glück mit den 40+1 Bytes.

Ich bin beim Suchen und "abschreiben" im Netz auf dieses Beispiel gestoßen und war neugierig, was diese Befehle bedeuten.


dl7ukk

Benutzeravatar
DjayBee
Beiträge: 626
Registriert: 17.08.2021 04:02
Has thanked: 385 times
Been thanked: 177 times
Kontaktdaten:

Re: byte checksum(byte* chunk, int length) { ...

Beitrag von DjayBee »

Erhard hat geschrieben:
23.02.2023 08:15
das sieht nach einer Routine aus, die entsprechend der Atari-SIO eine Prüfsumme erzeugt.
Korrekt.
Sie stammt offenbar aus dem Vorläufer des SDriveMax und wurde von Farb geschrieben.

Es werden einfach alle Bytes der Reihe nach addiert. In Assembler wird der Übertrag glaube ich mit reinaddiert, weiß ich aber nicht mehr genau und müßte ich nachschauen.
Ja, der Übertrag wird mit reinaddiert.

Aber egal wie groß der Datenblock ist, es werden nur die unteren 8 Bits (= 1 Byte) für die Prüfsumme verwendet.
Hier gibt's ein klares "jein".
Nicht die unteren 8 Bits werden verwendet, sondern das Ergebnis ist immer $00-$FF weil immer nur auf einem Byte addiert wird.
chkSum muss nur deshalb Integer sein, dass der Überlauf (a.k.a. Carry-Bit) erkannt wird (=$100).
Er wird direkt danach durch diesen Befehl (achtmal nach rechts schieben => $100 wird zu $1) wieder zum Byte addiert, wodurch das Ergebnis nur noch 8 Bit hat.

Code: Alles auswählen

chkSum+chunk[i])>>8
Als Ergebnis liefert sie 1 Byte zurück, die Prüfsumme eben.

Allerdings würde ACTION! bei dem Konstrukt richtig abkotzen, denn innerhalb der Funktion wird "chksum" als Integer definiert und bei der Rückgabe als Byte.
Yep, aber manchmal ist die Gelassenheit von C in Bezug auf Typecasts durchaus hilfreich.

Vermutlich funktioniert die Routine nicht mit Datenblöcken von mehr als 256 Bytes, da dann das Ergebnis größer als 16 Bit wird oder werden kann.
Doch, das sollte gehen. Es wird ja immer nur wieder auf das eine Byte draufaddiert.
Mit größeren Datenblöcken steigt aber das statistische Risiko an, dass eventuelle Fehler sich so ergänzen, dass die Prüfsumme zufällig wieder stimmt.

Erhard
Beiträge: 558
Registriert: 04.11.2021 15:52
Has thanked: 52 times
Been thanked: 111 times
Kontaktdaten:

byte checksum(byte* chunk, int length) { ...

Beitrag von Erhard »

Hi,

DjayBee hat geschrieben:
23.02.2023 12:26
Nicht die unteren 8 Bits werden verwendet, sondern das Ergebnis ist immer $00-$FF weil immer nur auf einem Byte addiert wird.
so war das gemeint. Hab ich schlecht ausgedrückt, sorry.

DjayBee hat geschrieben:
23.02.2023 12:26
Doch, das sollte gehen. Es wird ja immer nur wieder auf das eine Byte draufaddiert.
Im Moment würde ich dagegen Wetten, zumindet eine kleine Pizza.

Die Prüfsumme über einen 4K großen Datenblock kann bis zu $FF000 betragen. Das sind 24 Bit. Da die oberen 8 Bit nicht in die Berechnung einfließen würden müßte das Ergebnis falsch sein, wenn man bei der Addition nur ein 16-Bit Ergebnis berücksichtigt, oder?

CU, Erhard

Benutzeravatar
DjayBee
Beiträge: 626
Registriert: 17.08.2021 04:02
Has thanked: 385 times
Been thanked: 177 times
Kontaktdaten:

Re: byte checksum(byte* chunk, int length) { ...

Beitrag von DjayBee »

Erhard hat geschrieben:
23.02.2023 15:12
Die Prüfsumme über einen 4K großen Datenblock kann bis zu $FF000 betragen. Das sind 24 Bit. Da die oberen 8 Bit nicht in die Berechnung einfließen würden müßte das Ergebnis falsch sein, wenn man bei der Addition nur ein 16-Bit Ergebnis berücksichtigt, oder?
Die Addition erfolgt für jedes Byte einzeln und hat jedes Mal ein Ergebnis $00-$FF.

Zwei Byte addiert können max. $FF+$FF=$1FE ergeben.
Nach dem 8-fach Shift ergeben sich damit $01 aus dem High-Byte und $FE als Lo-Byte. Die werden addiert und ergeben $FF.

Erhard
Beiträge: 558
Registriert: 04.11.2021 15:52
Has thanked: 52 times
Been thanked: 111 times
Kontaktdaten:

byte checksum(byte* chunk, int length) { ...

Beitrag von Erhard »

Hi,

DjayBee hat geschrieben:
23.02.2023 15:18
Die Addition erfolgt für jedes Byte einzeln und hat jedes Mal ein Ergebnis $00-$FF.
dann habe ich evtl DL7UKK falsch verstanden. Er schrieb, die Routine addiert erst den gesamten Block in eine 16-Bit Zahl, welche dann in zwei 8-Bit Werte gesplittet und diese beiden Werte dann addiert würden:

dl7ukk hat geschrieben:
23.02.2023 10:48
Alle Bytes des Frames-1 zusammen zählen. (-1, das letzte Byte ist die Prüfsumme). Die Summe, eine 16 Bit-Zahl, in 8+8 Bit zerlegen und die beide 8 Bit-Werte zusammen zählen. Das klappte zumindest, bei den von mir untersuchten Frame immer so.
CU, Erhard

Benutzeravatar
dl7ukk
Beiträge: 532
Registriert: 25.08.2021 23:03
Has thanked: 69 times
Been thanked: 99 times
Kontaktdaten:

Re: byte checksum(byte* chunk, int length) { ...

Beitrag von dl7ukk »

na, ja

so blöd habe ich das geschrieben!

Aber es stimmt bei den 40+1 Bytes Frame.
40(dec) * FF = 0x28 * 0xFF = 0x27D8
0x27+0xD8 = 0xFF

und meine kleine Welt war in Ordnung. Ich habe keine Ahnung und weiß auch nicht wie viele Bytes maximal vom Druckertreiber des OS an den Drucker geschickt werden können.
Ich habe gerade gelernt, das der verdammte Treiber des OS bei mehr als 60 Zeichen kein $9B für CR/LF schickt. Und nun muß ich mich darum kümmern....


dl7ukk

Erhard
Beiträge: 558
Registriert: 04.11.2021 15:52
Has thanked: 52 times
Been thanked: 111 times
Kontaktdaten:

byte checksum(byte* chunk, int length) { ...

Beitrag von Erhard »

Hi,

dl7ukk hat geschrieben:
23.02.2023 21:47
Ich habe keine Ahnung und weiß auch nicht wie viele Bytes maximal vom Druckertreiber des OS an den Drucker geschickt werden können.
Meiner Erinnerung nach macht die CIO beim Drucker immer max 40 Bytes. Über die SIO müßte man eigentlich 64K an einem Stück senden können - außer ich vertue mich und die Zerstückelung auf 40 Bytes findet irgendwo in den Tiefen der SIO statt. Da müßte ich mich echt durch die Quellen des XE OS arbeiten ...

In Assembler ist die Berechnung der Prüfsumme glaube ich ziemlich einfach. Wenn man davon ausgeht, daß das aktuelle Byte im Akku ist und daß die Variable PSUMME auf eine Speicherstelle in Seite 0 zeigt müßte sich ergeben:

PHP
PHA
CLC
ADC PSUMME
ADC #0
STA PSUMME
PLA
PLP

Und dabei ist das Retten von Prozessorstatus und Akku nur dann erforderlich, wenn man es braucht. Also 7 Bytes.

CU, Erhard

JoSch
Beiträge: 132
Registriert: 25.08.2021 21:40
Has thanked: 56 times
Been thanked: 52 times
Kontaktdaten:

Re: byte checksum(byte* chunk, int length) { ...

Beitrag von JoSch »

Erhard hat geschrieben:
24.02.2023 08:47
Hi,
Meiner Erinnerung nach macht die CIO beim Drucker immer max 40 Bytes. Über die SIO müßte man eigentlich 64K an einem Stück senden können - außer ich vertue mich und die Zerstückelung auf 40 Bytes findet irgendwo in den Tiefen der SIO statt. Da müßte ich mich echt durch die Quellen des XE OS arbeiten ...
Das ist definitiv so. Das OS zerlegt alle Übertragungen in 40 Bytes.
Ich glaube, das liegt an irgendeinen der ersten Generation von Ataridruckern (weiß nicht mehr welcher genau). Dieser Drucker kann nur 40 Bytes puffern, und anscheinend wird deswegen jede Übertragung auf 40 Bytes begrenzt.

Benutzeravatar
dl7ukk
Beiträge: 532
Registriert: 25.08.2021 23:03
Has thanked: 69 times
Been thanked: 99 times
Kontaktdaten:

Re: byte checksum(byte* chunk, int length) { ...

Beitrag von dl7ukk »

Danke JoSch,
.
Das OS zerlegt alle Übertragungen in 40 Bytes .... von Ataridruckern
dass ist ein wichtiger Hinweis für uns. Erspart viel Denk-Arbeit.

dl7ukk

Benutzeravatar
24sumo
Beiträge: 192
Registriert: 17.08.2021 08:53
Has thanked: 48 times
Been thanked: 38 times
Kontaktdaten:

Re: byte checksum(byte* chunk, int length) { ...

Beitrag von 24sumo »

https://www.atariarchives.org/mmm/iocbs.php

PRNBUF
960-999 03C0-03E7

This is the print buffer, 40 bytes long, used in sending data to a printer. See PBPNT (29; $001C) and PBUFSZ (30; $001E) for details on how this works.

Antworten

Wer ist online?

Mitglieder in diesem Forum: 0 Mitglieder und 1 Gast