byte inverteren ?

Ja, het is goed IN de code al eea te documenteren.

Zo documenteer ik met:


static int status; 

dat de beginwaarde hiervan niet van belang is voor mij programma, en


static int status=0; 

dat de beginwaarde WEL belangrijk is voor mijn programma.

En zoals Blurp voorstelt kan je met


char c;

een variabele declareren waar je 1 karakter in opslaat... en met


uint8_t c; 

een variabele waar je precies 8 bitjes in verwacht.

Het wordt vervelend als de compiler dan met dingen als memcpy of strcpy gaat zeuren:


warning: pointer targets in passing argument 1 of ‘tests’ differ in signedness
four NANDS do make a NOR . Kijk ook eens in onze shop: http://www.bitwizard.nl/shop/

Op 24 mei 2020 07:06:34 schreef blurp:
[...]

Effe muggeziften: Dit werkt alleen als een char 8 bits is.

Je hebt helemaal gelijk. Als je een bijv 32-bits variabele kiest, dan moet je 0xFF veranderen in 0xFFFFFFFF enz.

Op 23 mei 2020 22:10:01 schreef Arco:
[...]
Met XOR ook, geen verschil... (wat dacht je dat die tilde 'onder de motorkap' doet?... ;) )

Effe getest met https://godbolt.org/z/A6a69_
tilde levert totaal andere code op als xor. Is ook wel logisch, want tilde grijpt in op het hele byte en xor alleen op aangewezen bitjes. Het hangt ook af voor welke processor je compileert. Heeft de processor een instructie voor xor of niet en heeft de processor een instructie voor tilde?

Op 24 mei 2020 19:12:50 schreef ohm pi:
Als je een bijv 32-bits variabele kiest, dan moet je 0xFF veranderen in 0xFFFFFFFF enz.


int main (int argc, char **argv)
{
  int v;

  v = 0xaa;
  v ^= 0xff;

  printf ("%x\n", v);
  exit (0);
}

four NANDS do make a NOR . Kijk ook eens in onze shop: http://www.bitwizard.nl/shop/
Patrick de Zeester

Golden Member

Op 24 mei 2020 19:25:54 schreef ohm pi:
[...]Effe getest met https://godbolt.org/z/A6a69_
tilde levert totaal andere code op als xor. Is ook wel logisch, want tilde grijpt in op het hele byte en xor alleen op aangewezen bitjes. Het hangt ook af voor welke processor je compileert. Heeft de processor een instructie voor xor of niet en heeft de processor een instructie voor tilde?

Dat is vreemd; bij mij zie ik in beide gevallen exact dezelfde code.

De volgende C code:


unsigned char invert_1(unsigned char byte)
{
   unsigned char inv_byte = byte ^ 0xFF;

   return inv_byte; 
}

unsigned char invert_2(unsigned char byte)
{
   unsigned char inv_byte = ~byte;

   return inv_byte; 
}

Produceert met AVR GCC -O2:

invert_1(unsigned char):
        com r24
ret
invert_2(unsigned char):
        com r24
ret

In het geval dat je XOR doet met 0xFF dan heeft met een 8-bits variabele ook een identiek effect als de tilde operator. Daarom is het ook niet zo vreemd is dat een optimizing C compiler(-O2 optie) in beide gevallen identieke output produceert.

Hier is een vrij obscure compiler die het verschillend doet.
Optimalisatie is uitgezet.

Bovenstaande test is niet goed.
Volgende test is beter.
Hier dwing ik de compiler om in de eerste functie te xor-en.
Dat doe ik door te xor-en met 0xFE. Er is dan geen snellere route mogelijk
De tweede functie laat ik ongewijzigd en laat ik de compiler gewoon zijn werk doen. Optimalisatie is uitgeschakeld.
In de eerste functie zie je dat de instructie 'xor' aangeroepen wordt.
In de tweede functie zie je dat de instructie 'not' aangeroepen wordt.
Ook 'onder de motorkap' wordt hier de 'xor' en 'tilde' verschillend behandeld.
Dat hangt oa af van de mogelijkheden die de gebruikte processor biedt

Arco

Special Member

De eerste processor is zo te zien een pic, de tweede een x86, die kun je niet met elkaar vergelijken.
De x86 heeft een veel complexere structuur.

Maar ongeacht de structuur, een XOR is een XOR en altijd snel.

Arco - "Simplicity is a prerequisite for reliability" - hard-, firm-, en software ontwikkeling: www.arcovox.com
Patrick de Zeester

Golden Member

Op 25 mei 2020 18:14:02 schreef ohm pi:
Bovenstaande test is niet goed.
Volgende test is beter.
Hier dwing ik de compiler om in de eerste functie te xor-en.
Dat doe ik door te xor-en met 0xFE. Er is dan geen snellere route mogelijk

Het probleem bij jouw test is dat XOR met 0xFE iets anders doet dan de tilde (~) operator. Het is dan ook niet meer dan logisch dat er andere machine code voor deze twee functies door de compiler gegenereerd wordt. Het is mij dan ook niet duidelijk wat jij nu met jouw test probeert te bewijzen.

De stelling was nu juist dat:

  1. Een XOR met 0xFF op een byte levert exact dezelfde uitkomst als de tilde operator op een byte; in beide gevallen worden alle bits in de byte geïnverteerd.
  2. Dat bij een goede compiler met optimalisaties ingeschakeld deze naar alle waarschijnlijkheid dezelfde machine code produceert voor inverteren van een byte ongeacht of dit nu gebeurt met ^0xFF of met de tilde operator.

Geen van deze stellingen worden weerlegt door jouw test.

@Arco ik heb op https://godbolt.org/z/A6a69_ geprobeerd met diverse processoren (AVR, x86, ARM ARM64, MIPS, MSP430, POWER64, RISC-V) en diverse compilers (GCC, CLANG, MSVC) in alle gevallen worden voor beide functies exact dezelfde machine code gegenereerd indien de optimizer (-O2) aanstaat. Omdat beide functies voor de bovenstaande stelling een identiek resultaat behoren te produceren, is het niet zo vreemd dat identieke machine code gegenereerd wordt - in dit geval is de instructie set van de processor niet zo relevant voor de bovenstaande stelling.

Op 25 mei 2020 22:57:02 schreef Patrick de Zeester:
[*]Dat bij een goede compiler met optimalisaties ingeschakeld deze naar alle waarschijnlijkheid dezelfde machine code produceert voor inverteren van een byte ongeacht of dit nu gebeurt met ^0xFF of met de tilde operator.

En... Dat met uitgeschakelde optimalisaties je vast bij de xor gewoon een xor met 0xff krijgt, maar na optimalisatie pas dezelfde code als een ~ operatie.

Ik heb:


unsigned char test1 (unsigned char t)
{
return ~t;
}

unsigned char test2 (unsigned char t)
{
return t^0xff;
}

unsigned char test3 (unsigned char t)
{
return 0xff-t;
}

met x86-64-gcc, AVR-gcc en met arm-gcc gecompileerd. Alledrie de functies leveren bij alle drie de compilers precies dezelfde code op. (na optimalisatie). Bij de arm-gcc compiler kan je zien dat het werken met de byte in de ARM tijd kost: Hij inverteert het hele 32 bit register en doet dan een AND met 0xff. De char vervangen door "int" en het scheelt een instructie!

[Bericht gewijzigd door rew op maandag 25 mei 2020 23:18:59 (37%)

four NANDS do make a NOR . Kijk ook eens in onze shop: http://www.bitwizard.nl/shop/

Op 25 mei 2020 22:57:02 schreef Patrick de Zeester:
Het is mij dan ook niet duidelijk wat jij nu met jouw test probeert te bewijzen.

Op 23 mei 2020 22:10:01 schreef Arco:
[...]
Met XOR ook, geen verschil... (wat dacht je dat die tilde 'onder de motorkap' doet?... ;) )

De stelling was dat de tilde 'onder de motorkap' omgezet wordt naar een XOR instructie.
Die stelling is met mijn voorbeeldcode ontkracht.
Alleen in de toevallige omstandigheid dat xor uitgevoerd wordt met 0xFF levert de compiler bij goed uitgevoerde optimalisatie dezelfde code op en meestal is dat de code die hoort bij de tilde.

[Bericht gewijzigd door ohm pi op dinsdag 26 mei 2020 02:02:43 (15%)

In de eerste instantie vertaalt de compiler


  v = ~v;

in iets als


  load v, r0
  com r0
  store r0, v

En voor


  v = v ^ 0xff;

iets als


   load v, r0
   load 0xff, r1
   exor r0, r1, r0
   store r0, v

Dit is zonder optimalisatie. Maar als er geoptimaliseerd moet worden dan ziet ie dat het resultaat precies hetzelfde is, en dat ie van deze sequences de kortste en snelste kan kiezen.

Laatst had ik een stukje test-code geschreven (voor CO). Ik telde steeds de loop variabele en de input parameter van de functie bij mekaar op. Bij optimalisatie bleek de functie samen te vatten tot return t*16+11; Niks loop. Dat had ie er allemaal uitgehaald. De optimalisatie is best goed.

four NANDS do make a NOR . Kijk ook eens in onze shop: http://www.bitwizard.nl/shop/