van decimaal naar binair ?


ik ga dat later beter testen en de bovenstaande reacties beter lezen.

Fijn dat je ons op de hoogte houdt, @trix, doe zo voort. Sukses ermee en bovenal veel pret bij het leren!

dat ascii gebeuren is toch wel een beetje lastig, voor een leek

Als het "ascii"-gebeuren u fascineert - het is eigenlijk niet meer dan een vertaaltabel, hoor - dan kan het nuttig zijn een streepje assembler te schrijven, zoals ook o.a. @arco reeds aangaf. Alleen weet ik vandaag geen processor aan te bevelen om dat op te doen, zelf schreef ik assembler voor 6502 maar die is ietwat exotisch geworden :)

[Bericht gewijzigd door big_fat_mama op 12 juli 2020 11:46:23 (16%)]

hoe beter de vraag geschreven, zoveel te meer kans op goed antwoord
trix

Golden Member

ik heb trouwens nog niks met de terminated 0 gedaan :S

eigenwijs = ook wijs

De PIC16Fxxx is prima in assembly te doen... (MPASM)
Nadeel van assembly is alleen dat bij complexe programma's het onderhoud / wijzigingen tijdrovend zijn...

Arco - "Simplicity is a prerequisite for reliability" - hard en software ontwikkeling: www.arcovox.com
Jochem

Golden Member

Op 12 juli 2020 11:42:59 schreef Arco:
Ach ja,

Het verschil tussen de verschillende programmeertalen is een kwestie van semantiek, de gecompileerde code is meestal gelijk.
Alleen vind ik Basic veel beter leesbaar, en daarom heb ik daarvoor gekozen. Als je beiden vergelijkt:

pic basic code:


If (a = b) then c = 0 else c = 2

c code:


c = (a == b) ? 0 : 2;

dan kun je toch niet volhouden dat de 'C' versie duidelijker is?... ;)

Dat je iets op een bepaalde manier KUNT schrijven, betekent niet dat je het zo MOET schrijven. Je kunt in C gewoon ook if/else gebruiken.

c code:

if (a == b) 
  c = 0;
else
  c = 2;

In sommige gevallen is het fijn om de korte schrijfwijze te gebruiken, juist om geen onnodige extra if-blokken te krijgen. Het voorbeeld van deKees is voor mij erg duidelijk leesbaar. Je kijkt met een masker naar een specifiek bit, en afhankelijk daarvan krijg je '1' of '0'. Juist door dat met een ternary operator te schrijven blijft het overzichtelijk en houd je maar 1 plek waar je naar het display schrijft.

Heb geduld: alle dingen zijn moeilijk voordat ze gemakkelijk worden.

@trix

code:


   RAM_content >> 1;

Dit doet niks. Je schuift de waarde uit RAM_content 1 positie naar rechts, en gooit het resultaat weg. Als je het resultaat wilt terug schrijven in RAM_content dan heb je een assignment nodig:

code:


   RAM_content = RAM_content >> 1;

of verkort:

code:


   RAM_content >>= 1;

En hier gaat het ook fout

code:


   sprintf(s, "content  = %u", (lchar));

sprintf() krijgt hier de opdracht om een %u (unsigned decimal) getal af te printen en doet dat dan ook. Maar lchar is een pointer dus je krijgt de waarde van de pointer ipv de string die je wilt.
Als je een string wilt printen moet je %s gebruiken.

Maar dan ontbreekt de nul terminator nog. Geeft niet als je de lengte van de string beperkt "%.8s", en anders moet je een terminator schrijven:

code:


   lchar[8] = 0;

Hier allebei in het voorbeeld

code:


   for (cnt = 7; cnt >= 0; cnt = cnt -1)
   {
      lchar[cnt] = (0x30 + (RAM_content & 0x01));
      RAM_content >>= 1;
   }
   // below: put the content on the display
   lchar[8]=0;
   sprintf(s, "content  = %.8s", lchar);
   Lcd4_Set_Cursor(1,16);
   Lcd4_Write_String(s);

En in C is er inderdaad verschil tussen enkele en dubbele quotes.
'0' is een char, waarde 48 (decimal) = waarde 30 (hex).
"0" is een string met een '0' (0x30) en een null terminator (0x00). Als je dat in je programma gebruikt krijg je het adres van die string.

Je mag dan nette code in C kunnen schrijven, maar in de praktijk zie je dat toch weinig. (ik heb al heel wat C headers vertaald en da's bijna altijd ellende)
In het verleden C source moeten 'ontrafelen' waar vergelijkingen / and / or / shifts tot één geheel op mekaar geprakt stonden op regels van anderhalf A4'tje breed... :(

Ben net klaar met vertalen 20.000+ regels C headers, daar wordt je niet echt vrolijk van...

Gebruik van constants zou het leven makkelijker moeten maken. Ik twijfel daar wel aan als je dit soort namen tegenkomt voor een constant... ;)

code:


#define IPEC_Q931Cause70OnlyRestrictedDigitalInformationBearerCapabilityIsAvailable  0x1E

[Bericht gewijzigd door Arco op 12 juli 2020 13:43:55 (23%)]

Arco - "Simplicity is a prerequisite for reliability" - hard en software ontwikkeling: www.arcovox.com

Alleen weet ik vandaag geen processor aan te bevelen om dat op te doen

??? We hebben het hier toch over een AtMega328 ?

code:


   mov  R26,R24    ; x
   ldi  R27,0x80   ; Mask = 0x80
L001:
   ldi  R24,0x30   ; '0'
   and  R26,R27    ; x & Mask
   breq L002       ; ?
   inc  R24        ; '0' + 1 
L002:
   rcall Lcd_Write_Char 
   lsr  R27       ; Mask >>= 1
   brne L001      ; while Mask != 0
   ret

Maar toch is de assembler makkelijker te lezen als je de C versie erachter zet. :)

edit:
Wel de goede kant schuiven natuurlijk..

:) dat lijkt niet eens zo danig verschillend van wat ik me herinner van de 6502 ...
"mov" herinnert eerder aan de x86-familie
"bre" en "brne" klinken dan weer 6502/6800-achtig.
Ik geef nederig toe dat ik al lang geen assembler meer schrijf, python meestal nu, en bash; en af en toe een beetje C.

hoe beter de vraag geschreven, zoveel te meer kans op goed antwoord

Voor de basic liefhebbers:

code:


void WriteBinary(uint8_t x)
{
   for(uint8_t Mask = 0x80; Mask != 0; Mask >>= 1)
   {  Lcd4_Write_Char( (x & Mask) ? '1' : '0');
   }
}

Kun je ook uitschrijven als:

code:


void WriteBinary(uint8_t x)
{
   for(uint8_t Mask = 0x80; Mask != 0; Mask = Mask >> 1)
   {  
      if( (Mask & x) == 0)
         Lcd4_Write_Char( '0');
      else
         Lcd4_Write_Char( '1');
   }
}

Inderdaad, alweer zijn er meerdere wegen naar de stad der steden... :) En welke de beste is, dat is een kwestie van smaak en cultuur en opvoeding en gewoontes. De uiteindelijke uitvoerbare code zal vermoedelijk identiek zijn, met dank aan de optimalizerende compilers.

hoe beter de vraag geschreven, zoveel te meer kans op goed antwoord

Hier nog een hele discussie over hetzelfde onderwerp.
Daar zitten wel een paar creatieve oplossingen tussen. :)

https://stackoverflow.com/questions/111928/is-there-a-printf...ary-format

trix

Golden Member

dekees bedankt voor de aanpassingen, dat van %c naar %s had ik zelf al gedaan, daar heb je waarschijnlijk over heen gelezen.

eigenwijs = ook wijs
buckfast_beekeeper

Golden Member

Op 12 juli 2020 11:42:05 schreef Jochem:
[...]Je hebt het over C?

C++, wat algemeen gebruikt kan worden binnen Arduino of Atmel Studio.

Op 12 juli 2020 11:42:59 schreef Arco:
Ach ja,

Het verschil tussen de verschillende programmeertalen is een kwestie van semantiek, de gecompileerde code is meestal gelijk.
Alleen vind ik Basic veel beter leesbaar, en daarom heb ik daarvoor gekozen. Als je beiden vergelijkt:

pic basic code:


If (a = b) then c = 0 else c = 2

c code:


c = (a == b) ? 0 : 2;

dan kun je toch niet volhouden dat de 'C' versie duidelijker is?... ;)

Veel hangt af van de taal die je gewoon bent. Vraag aan een buitenlander hoe gemakkelijk Nederlands is. Niet voor niets wordt er van een 'taal' gesproken.

[Bericht gewijzigd door buckfast_beekeeper op 12 juli 2020 17:10:51 (64%)]

Van Lambiek wordt goede geuze gemaakt.

Veel hangt af van de taal die je gewoon bent.

Een goede programmeertaal is 'self-explanatory' (je weet meteen wat bedoeld wordt)
Met bijv. '?' en ':' moet je eerst een reference guide raadplegen... ;)

Arco - "Simplicity is a prerequisite for reliability" - hard en software ontwikkeling: www.arcovox.com
buckfast_beekeeper

Golden Member

Het grootste deel van mijn programmeeropleiding was Java en dan is c = ( a== b)? 0: 2); een heel normale verschijning. Principes blijven hetzelfde. De ene taal schrijft

pic basic code:


if( iets)
    doe iets 'commentaar
end if

een ander doet het dan weer

c code:


if (iets){
    doe iets; // commentaar
}

C, C++ en Java zijn wat dat betreft heel gelijkaardig. VBA is toch altijd weer wennen. Ondanks dat ik daar honderden bladzijden heb van geschreven.

Om het bij de woorden van mijn eerste docent te houden. Er zijn een aantal basis regels maar dat zijn geen wetten. Als je een bepaalde stijl gaat gebruiken, doe het dan consequent.

Van Lambiek wordt goede geuze gemaakt.
trix

Golden Member

Op 12 juli 2020 12:01:12 schreef deKees:
@trix

code:


   for (cnt = 7; cnt >= 0; cnt = cnt -1)
   {
      lchar[cnt] = (0x30 + (RAM_content & 0x01));
      RAM_content >>= 1;
   }
   // below: put the content on the display
   lchar[8]=0;
   sprintf(s, "content  = %.8s", lchar);
   Lcd4_Set_Cursor(1,16);
   Lcd4_Write_String(s);

dit werkt inderdaad, bedankt dekees.
toch een vraagje: wat doet die 8 in: sprintf(s, "content = %.8s", lchar); ?

eigenwijs = ook wijs

De .8 in %.8s zorgt ervoor dat je max 8 letters afdrukt. Zonder de punt zou het een minimum zijn.
Dat is dus een andere manier om aan te geven hoeveel letters je op het scherm krijg.

EricP

mét CE

Een goede programmeertaal is 'self-explanatory' (je weet meteen wat bedoeld wordt)

Dat is mij nou met een gedrocht als Basic nooit gelukt. Zelfs de manual maakte het niet duidelijk. Daar moest een disassembler aan te pas komen om te kijken wat het nou eigenlijk doet...

Wat dat betreft is C toch een stuk vriendelijker. In zo'n beetje elke manual, tutorial of wat dan ook kun je zo vinden wat die operators doen...

De uiteindelijke uitvoerbare code zal vermoedelijk identiek zijn, met dank aan de optimalizerende compilers.

Dat wisselt sterk. En bedenk ook dat als je code redelijk portable moet zijn, je bepaalde dingen juist wel of niet moet doen.

Ik geef nederig toe dat ik al lang geen assembler meer schrijf, python meestal nu, en bash; en af en toe een beetje C.

Ik heb nog nooit een assembler geschreven. Daar zijn prima varianten van door andere geschreven. Is het zo lang geleden dat je ook al vergeten bent dat het taaltje assembly heet? :+ (die was te makkelijk).
Ook al ben je niet meer actief met zo'n taal bezig... De denkwijze ken je nog steeds. En ik ben er van overtuigd dat je er nog steeds makkelijk op terug grijpt. Inmiddels doe ik vooral C en een beetje bash - als je dat een programmeertaal wilt noemen. Maar als er iets gebeurt wat ik niet snap, dan lees ik ook zo AVR assembly weer. En inderdaad, soms met 'het boek' ernaast om ff te kijken welke flags een instructie precies raakt en welke niet - dat verwatert. 'Niet snappen' zit overigens vaak in de hoek van 'waarom is dit zo traag??'. Heel vaak blijkt dat als je het de compiler iets anders voorschotelt, de optimzer er beter mee uit de voeten kan. Een hele enkele keer is de optimizer 'te veilig' (wat op zich prima is...) en kun je in die context korter door de bocht.

Anyway... fijn dat trix iets heeft wat werkt.

Ik heb nog nooit een assembler geschreven. Daar zijn prima varianten van door andere geschreven.

Je kunt zelfs bestaande assemblers aanpassen aan nieuwe processoren. Bijv. de TASM assembler (Telemark Assembler van Thomas Anderson)
Je hoeft daarbij 'alleen' maar een tabel te maken voor de instructies zodat de parser van de assembler ze uit kan voeren... ;)

Ik heb die vroeger altijd gebruikt voor de 8048/8051/68HC11/Z80...
(ooit wel eens begonnen aan een nieuwe processortabel toevoegen, maar is er nooit van gekomen...)

http://gamearchive.askey.org/Video_Games/Stuff/programs/tasmx/

Arco - "Simplicity is a prerequisite for reliability" - hard en software ontwikkeling: www.arcovox.com
EricP

mét CE

We gaan off topic (sorry trix...). Ik kende TASM als Turbo Assembler. DOS tool van Borland en die deed het best leuk, in tegenstelling tot MASM (wat was dat een drama in die tijd...)

Stom dat ik eigenlijk niet eens meer weet welke assembler ik destijds voor 8051 gebruikte. Zou het aan grijze haren liggen? :+
Laatste stukjes assembly op een 8051 was 'inline' in sdcc.

TASM (de variant die Arco noemt) was misschien wel leuk geweest voor een ASIC met een custom core (naast een 8051 core) waar ik een tijdje mee gewerkt heb. Uiteraard ook in assembly en DIE assembler was echt een drama met zo nu en dan onvoorspelbare output. Ik kan me nog herinneren dat we toen in de make files 5x een run met de assembler op dezelfde code deden. Daarna compares op de object files deden en als er 3 dezelfde tussen zaten, dan werkte het ook (dus die waren blijkbaar 'goed').
Waarschijnlijk een stuk uninitialized memory in de assembler. Geen documentatie van opcodes. Je redt je er maar mee. Maar ja, die ASIC kon in die tijd wat dingen die de opdrachtgever interessant vond. Dus dit soort 'ongemakken' nam je maar voor lief (en ja, het heeft even geduurd voordat ik door had dat de ellende in de assembler zat en niet in mijn gebrek aan kennis van het chippie :) - toch de meest voor de hand liggende oorzaak in de beginne!)

Op 22 juli 2020 13:11:33 schreef EricP:
We gaan off topic ... DOS tool van Borland en die deed het best leuk, in tegenstelling tot MASM (wat was dat een drama in die tijd...)

Niks mis mee, kon je asm files mee bouwen in alle memory modellen (small/medium/large) en heb er volgens mij nooit een bug in ontdekt (de C-compiler van MS wel). Daar (MASM) heb ik enorm veel code mee gemaakt.

Zo kan het ook:

c code:


   for (cnt = 0, mask = 0x80; cnt <= 7; cnt++, mask >>= 1)
   {
      lchar[cnt] = (RAM_content & mask) ? '1':'0');
   }
   // terminate string
   lchar[8] = '\0';

Hier wordt RAM_content niet overschreven en kun je er direct je array met index inzetten.

cnt en mask kunnen nu een uint8_t zijn en lchar een array van 9 chars die je direct kunt printen.

-edit- \1 en \0 in die ? construct gecorrigeerd, was fout.

Henri's Law 1: De wet van behoud van ellende. Law 2: Ellende komt nooit alleen.
Jochem

Golden Member

Ik vind zo'n for met dubbele instructies de grens van het leesbare opzoeken. Zo hebben we kennelijk allemaal onze voorkeuren.

Verder snap ik de backlashes voor de 1 en de 0 niet, daar wil je toch gewoon printbare karakters? De null als afsluiter van de string is wel duidelijk natuurlijk.

Heb geduld: alle dingen zijn moeilijk voordat ze gemakkelijk worden.

mijn voorkeur:

code:


for (i = 0; i < 8; i++)
    lchar[i] = RAM_content & (0x80>>i) ?'1':'0';
lchar[i] = '\0'; // terminate string

Ik vind het fijn om de "deze loop gaat 8 keer", de 8 echt in m'n code te zien. De extra variabele vind ik niet nodig -> ik heb niet die dubbele constructies met de comma. De "terminate" in de henri62 code KAN niet goed zijn met de \0 al in 255 van 256 mogelijke inputwaardes. De bedoeling was overduidelijk om de ascii chars 0 en 1 te gebruiken.

en eigenlijk is:

code:

itoa (RAM_content, lchar, 2);

het beste. Maar dan is het denk ik niet meer altijd precies 8 karakters.

Nog een alternatief:

code:

for (i = 0; i < 8; i++)
    lchar[i] = '0' + ((RAM_content >> (7-i)) & 1);
lchar[i] = '\0'; // terminate string

Ik heb vluchtig een paar posts terug iets gezien over getallen bij chars optellen. Dus zoiets zal dat wel getriggerd hebben. Ik heb daar niets op tegen.

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

[edit: oops: in m'n andere browser stond dit nog "klaar om te posten"]

Op 22 juli 2020 11:23:20 schreef EricP:
Ik heb nog nooit een assembler geschreven. ... :+

Ik heb inderdaad al heel lang geen assembler meer geschreven. Ik heb er denk ik twee geschreven! 6502 op de commodore 64. En 1 voor een op m'n vakgroep gemaakte architectuur. (ik heb 1 of 2 van de chips, 20 of 40% van de wereldproductie, 33 of 66% van de resterende wereldvoorraad).

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

Op 22 juli 2020 22:57:24 schreef Jochem:
Ik vind zo'n for met dubbele instructies de grens van het leesbare opzoeken. Zo hebben we kennelijk allemaal onze voorkeuren.

Klopt zit wel op het randje.

Op 22 juli 2020 22:57:24 schreef Jochem:
Verder snap ik de backlashes voor de 1 en de 0 niet, daar wil je toch gewoon printbare karakters? De null als afsluiter van de string is wel duidelijk natuurlijk.

Oops foutje, die horen er inderdaad niet.

[Bericht gewijzigd door henri62 op 24 juli 2020 18:39:55 (30%)]

Henri's Law 1: De wet van behoud van ellende. Law 2: Ellende komt nooit alleen.