Enkla men fatala buggar

PIC, AVR, Arduino, Raspberry Pi, Basic Stamp, PLC mm.
Användarvisningsbild
sodjan
EF Sponsor
Inlägg: 43150
Blev medlem: 10 maj 2005, 16:29:20
Ort: Söderköping
Kontakt:

Re: Enkla men fatala buggar

Inlägg av sodjan »

Ja visst, här är kompilatorlistan med /NOOPTIMIZE.
Det är delen för själva "func" funktionen, jag har även här plockat bort
main() och annan kod som bara körs en gång eller inte alls. Det framgår
ju tydligt var rekurssionen gör med "BSR R26, FUNC"...

Kod: Markera allt

                                Machine Code Listing             5-JUN-2013 17:24:21  HP C V7.3-010-48L7K               Page 2
                                                                 5-JUN-2013 17:14:51  USER:[JANNE]REKURS.C;15

                                .PSECT  $CODE$, OCTA, PIC, CON, REL, LCL, SHR,-
                                        EXE, NORD, NOWRT
             0000       FUNC::
23DEFFD0     0000               LDA     SP, -48(SP)
B77E0000     0004               STQ     R27, (SP)
B75E0010     0008               STQ     R26, 16(SP)
B45E0018     000C               STQ     R2, 24(SP)
B7BE0020     0010               STQ     FP, 32(SP)
47FE041D     0014               MOV     SP, FP
47FB0402     0018               MOV     R27, R2
B21D0008     001C               STL     R16, n                                  ; R16, 8(FP)
22020020     0020               LDA     R16, 32(R2)                                                                         ; 001607
A23D0008     0024               LDL     R17, n                                  ; R17, 8(FP)
47E05419     0028               MOV     2, R25
A7420030     002C               LDQ     R26, 48(R2)
A7620038     0030               LDQ     R27, 56(R2)
6B5A4000     0034               JSR     R26, DECC$GXPRINTF                      ; R26, R26
A01D0008     0038               LDL     R0, n                                   ; R0, 8(FP)                                 ; 001608
40003010     003C               ADDL    R0, 1, R16
47E03419     0040               MOV     1, R25
A7620040     0044               LDQ     R27, 64(R2)
D35FFFED     0048               BSR     R26, FUNC
47FD041E     004C               MOV     FP, SP                                                                              ; 001609
A75D0010     0050               LDQ     R26, 16(FP)
A45D0018     0054               LDQ     R2, 24(FP)
A7BD0020     0058               LDQ     FP, 32(FP)
23DE0030     005C               LDA     SP, 48(SP)
6BFA8001     0060               RET     R26
Användarvisningsbild
pbgp
Inlägg: 1447
Blev medlem: 11 november 2010, 09:09:22
Ort: Uppsala
Kontakt:

Re: Enkla men fatala buggar

Inlägg av pbgp »

sodjan skrev:Aha! :-)
Det visade sig att funktionen optimerades till inline kod utan några CALL's
(förrutom till printf) och stacken kraschade så klar aldrig:

> 1. Inlining func into main
Nja, det är väl inte själva inline:andet som gör det utan det faktum att det är ett exempel på tail recurssion. Dvs det sista som görs i funktionen är det rekursiva anropet och då kan stackutrymmet återanvändas. Sedan blev det en kodsnutt som kunde inline:as.

Vad kör du för kompilator, att det är på VMS ser jag :)
Användarvisningsbild
sodjan
EF Sponsor
Inlägg: 43150
Blev medlem: 10 maj 2005, 16:29:20
Ort: Söderköping
Kontakt:

Re: Enkla men fatala buggar

Inlägg av sodjan »

Kompilatorn står längst uppe till höger i kompileringslistan. :-)
Eller här:

$ cc /version
HP C V7.3-010 on OpenVMS Alpha V8.4
$

Jag provade även med :
$ cc /list/optimize=noinline/machine rekurs

Då behålls "func" funktionen men det rekursiva anropet blev en vanlig
loop internt i func istället för att det hela flyttades till main. Den ser
likadan ut som mitt första exempel med 8 rader men det ligger alltså i
func() istället för i main(). Ingen rekursivitet eller stackproblem alltså.
Användarvisningsbild
JimmyAndersson
Inlägg: 26308
Blev medlem: 6 augusti 2005, 21:23:33
Ort: Oskarshamn (En bit utanför)
Kontakt:

Re: Enkla men fatala buggar

Inlägg av JimmyAndersson »

Det finns ju många sätt att dela upp en byte till två nibble.
Om man gör såhär:

input = 0b01101010
high = input & 0b11110000
low = input & 0b00001111 << 4

..så kommer både high och low att ge 0b01100000. :)

Med tanke på vilken ordning som operanderna jobbar så är det ju en parentes som saknas. Dvs:
low = (input & 0b00001111) << 4


Allt för många verkar envisas med att skriva talen i hexadecimal "form"
och då ser man i bästa fall bara att variabeln low (i det här fallet) blev mindre än man förväntade sig...
Användarvisningsbild
AndLi
Inlägg: 17051
Blev medlem: 11 februari 2004, 18:17:59
Ort: Knivsta
Kontakt:

Re: Enkla men fatala buggar

Inlägg av AndLi »

Jimmy: Hur menar du med hexadecimalt inte ger samma info?
Och 0b är inte standard C på samma sätt som 0x är.

(Jo jag är en hex missbrukare...)
Användarvisningsbild
TomasL
EF Sponsor
Inlägg: 45175
Blev medlem: 23 september 2006, 23:54:55
Ort: Borås
Kontakt:

Re: Enkla men fatala buggar

Inlägg av TomasL »

0b............. förekommer inte alls i standarden.
Dock har en del processortillverkare lagt till det i sina kompilatorer, dock koden är inte porterbar, och kompilerar inte på en standardkompilator.
blueint
Inlägg: 23238
Blev medlem: 4 juli 2006, 19:26:11
Kontakt:

Re: Enkla men fatala buggar

Inlägg av blueint »

Det kan vara att de flesta kompilatorer ej stödjer 0b samt att alla som följer standard ej har denna notation som gör att folk envisas med 0x6A ;)
Användarvisningsbild
JimmyAndersson
Inlägg: 26308
Blev medlem: 6 augusti 2005, 21:23:33
Ort: Oskarshamn (En bit utanför)
Kontakt:

Re: Enkla men fatala buggar

Inlägg av JimmyAndersson »

AndLi:
Titta på vilket datablad som helst för AVR/PIC eller varför inte en LCD-display.
Där är varje parameter angiven såhär:

Parameternamn
bit 7 - Den här styr en grej
bit 6 - Den här styr en annan grej
osv...

Har man då en källkod med t.ex parameternamn = 0x47
så är det långt ifrån lika enkelt att se hur man har konfigurerat den här parametern.
Jämfört med om man skrivit parameternamn = 0b01000101

Ofta är det samma sak med värden som hade passat bättre i decimal form än hexadecimal form.
Det förekommer (lyckligtvis) inte så ofta på forumet.

Det är samma trassel varje gång man ska felsöka någon AVR/PIC-kod från nätet (t.ex forumet)
eftersom man måste sitta och "översätta" varenda hex till bin.


Det vore mycket intressant att se någon form av lista över vilka kompilatorer för mikroprocessorer som inte stödjer "0b".
Det binära talsystemet borde väl vara det mest lämpliga med tanke på att man oftast programmerar mot specifika bitar....
blueint
Inlägg: 23238
Blev medlem: 4 juli 2006, 19:26:11
Kontakt:

Re: Enkla men fatala buggar

Inlägg av blueint »

Kod: Markera allt

int main(){
printf("%d\n",1);
printf("0x%02X\n", 0b1100 );
return 0;
}
gcc -v
gcc version 2.95.3 (sparc-sun-solaris)

Ger:
zerob.c: In function `main':
zerob.c:3: nondigits in number and not hexadecimal
Exit 1
FreeBSD/i386 system compiler
Thread model: posix
gcc version 3.3.3

Ger:
zerob.c:3:20: invalid suffix "b1100" on integer constant
Exit 1
0b.. notationen skulle vara väldigt användbar men den saknar som sagt brett stöd.
blueint
Inlägg: 23238
Blev medlem: 4 juli 2006, 19:26:11
Kontakt:

Re: Enkla men fatala buggar

Inlägg av blueint »

Apropå fatala buggar:

"if( variable =! 0 )" är samma som "variable = 1;" .. :vissla:
Användarvisningsbild
JimmyAndersson
Inlägg: 26308
Blev medlem: 6 augusti 2005, 21:23:33
Ort: Oskarshamn (En bit utanför)
Kontakt:

Re: Enkla men fatala buggar

Inlägg av JimmyAndersson »

"0b.. notationen skulle vara väldigt användbar men den saknar som sagt brett stöd."

Det var lite kul att läsa den meningen efter att se testet av två gcc-kompilatorer. :wink:
Visst, gcc är väl spritt, men det är ju långt ifrån det enda som används av de som skriver/kompilerar kod för mikroprocessorer.

Jag tror att MPLAB (minns inte namnet på själva kompilatorn) är vanligare för PIC
och det finns garanterat något liknande som de flesta AVR-användare kör med.
(En titt i Elektronikforumets Mikroprocessor-avdelning verkar stödja det.)

-

Nu är ju just detta om hex/bin ingen *bugg*: Om "bin" inte stöds så får man ett meddelande om det.
Om däremot båda stöds och man väljer fel, kanske råkar skriva x istället för b, ja *då* får man förmodligen
fel resultat. En bugg.

Men mitt inlägg handlade om att man bör ha koll på vilken ordning som operanderna "jobbar" i.
Min kodsnutt var ett exempel på detta och vad som hände såg man tydligast med "binär visning" av talen.
Användarvisningsbild
AndLi
Inlägg: 17051
Blev medlem: 11 februari 2004, 18:17:59
Ort: Knivsta
Kontakt:

Re: Enkla men fatala buggar

Inlägg av AndLi »

JimmyAndersson skrev:AndLi:
Titta på vilket datablad som helst för AVR/PIC eller varför inte en LCD-display.
Fast nu var det ju ditt exempel vi pratade om, där säger du att man inte sett felet/förstått vad som hänt om man inte skrivit det i binärt?

Omskrivet blir det ju:
input = 0x6A
high = input & 0xF0
low = input & 0x0F << 4

..så kommer både high och low att ge 0x60.

Hex ger ju också infon om vilken nibbel som påverkats, eller blivit 0 i detta exempel.
JimmyAndersson skrev: Ofta är det samma sak med värden som hade passat bättre i decimal form än hexadecimal form.
Det förekommer (lyckligtvis) inte så ofta på forumet.
Där håller jag med, men tänk ditt exempel igen i decimalt :)

Omskrivet blir det ju:
input = 106
high = input & 240
low = input & 16 << 4

..så kommer både high och low att ge 96.

Då hade man fått tänka en extra gång innan man hängt med vad som hänt...
JimmyAndersson skrev: Det är samma trassel varje gång man ska felsöka någon AVR/PIC-kod från nätet (t.ex forumet)
eftersom man måste sitta och "översätta" varenda hex till bin.
Det sätter sig i det undermedvetna efter några miljoner rader kod :)
Och man blir inte kompilatorberoende, men visst kan även jag se fördelar med 0b ibland.
JimmyAndersson skrev: Det binära talsystemet borde väl vara det mest lämpliga med tanke på att man oftast programmerar mot specifika bitar....
Fast 0b syntaxen funkar ju fint på 8 bitars tal, men redan vid 16bitars börjar det kännas som risken att räkna fel på antalet nollor är stor, vid 32 och 64 börjar det bli väldigt långt.
Inte sagt att ett 0x 64 bitars tal blir så himla kort heller, men bör vara enklare att hålla koll på då det är fler olika siffror som kan hjälpa en att hålla koll på hur långt man räknat.

>det finns garanterat något liknande som de flesta AVR-användare kör med
Jag var övertygad om att gcc var vanligast till avr/atmegorna, men det beror säkert på att det är det jag själv använt.
Till PIC finns det väll inte någon gcc att kunna välja...
Användarvisningsbild
TomasL
EF Sponsor
Inlägg: 45175
Blev medlem: 23 september 2006, 23:54:55
Ort: Borås
Kontakt:

Re: Enkla men fatala buggar

Inlägg av TomasL »

MC32, dvs Microchips kompilator till PIC32 är gcc, dock lär det väl inte finnas några gcc-portar till 8-bitars processorerna, vad jag vet.
Användarvisningsbild
Icecap
Inlägg: 26106
Blev medlem: 10 januari 2005, 14:52:15
Ort: Aabenraa, Danmark

Re: Enkla men fatala buggar

Inlägg av Icecap »

Jag kan i vissa fall förstå 0b.... men om det är för att förtydliga vilka bit'ar som styrs på t.ex. en port (LCD_Enable = 1 osv) är det ändå fel!
Ett exempel:
#define LCD_Enable (1 << 3)
#define LCD_RS (1 << 4)
#define EEPROM_nOE (1 << 5)

då kan man vara extrem tydlig:
PORTA |= LCD_ENABLE + LCD_RS;
PORTA &= ~LCD_Enable;
osv.

Visst kan man göra det med 0b.... (om kompilern tillåter) men speciellt tydligt är det inte!

Och är det fasta värden (ställa register osv) är det bara att skriva det i kommentaren efter kommandot, då kan man skriva lite allmänt vad man gör och varför.
Användarvisningsbild
TomasL
EF Sponsor
Inlägg: 45175
Blev medlem: 23 september 2006, 23:54:55
Ort: Borås
Kontakt:

Re: Enkla men fatala buggar

Inlägg av TomasL »

Det är betydligt bättre att använda enum än #define, då en define kan re-defineras utan att man får fel/varningar.
Om man försöker omdefiniera en enum, får man ett felmeddelande.

Om, man tar Icecaps exempel ovan:

Kod: Markera allt

#define LCD_Enable (1 << 3)
#define LCD_RS (1 << 4)
#define EEPROM_nOE (1 << 5)


LCD_Enable (1 << 3) == 8
LCD_RS (1 << 4) ==16
EEPROM_nOE (1 << 5)==32
Blir det betydligt bättre att göra så här:

Kod: Markera allt

enum {LCD_Enable=8, LCD_RS=16, EEPROM_nOE=32};
Skriv svar