Hallo
Das "quick&dirty" bezog sich auf die Annahme, dass der Kompiler intern false als 0 speichert und deshalb jeder Wert größer 0 als true interpretiert wird. Ich wollte das nur mal wieder bewußt machen, denn "im Alltag" beachtet das eh niemand: while(1) sollte eigentlich while(true) lauten.
#define IsBitSet(ADDR,BIT) (((ADDR) & (1<<BIT)) > 0) // Fragt Bit = 1?
So würde das Ergebniss true oder false sein.
Das wollte ich mal genauer untersuchen, weil ich ja was lernen will. Mit C komme ich inwischen recht gut zurecht, aber mit Assembler kenne ich mich noch gar nicht aus. Dieses kleine Testprogramm wurde (ohne Optimierung!) mit 136 Bytes übersetzt:
IsBitSet() wird in zwei Varianten definiert, Variante eins prüft 1 oder 0, Variante zwei prüft true/false.Code:#define IsBitSet(ADDR,BIT) (((ADDR) & (1<<BIT))?1:0) // Fragt Bit = 1? #define IsBitSet2(ADDR,BIT) (((ADDR) & (1<<BIT)) > 0) int main(void) { int x, tmp; if(IsBitSet(x,0)) tmp=0x11; else tmp=0x22; if(IsBitSet2(x,0)) tmp=0x33; else tmp=0x44; while(1); return(0); }
Aus dem erzeugten Assemblerlisting habe ich die entscheidende Stelle rauskopiert und kommentiert (soweit mir das möglich ist):
Erstaunlicherweise ist die erste Variante kürzer, allerdings habe ich das Gefühl, mit tst r24 wird nur das Lowbyte geprüft. Beschreibung von breq:Code:.LM2: // if(( ldd r24,Y+3 // x ldd r25,Y+4 // x ist in Y+3 und Y+4 gespeichert andi r24,lo8(1) // & (1<<0)) andi r25,hi8(1) tst r24 // prüft ob ein Bit in R24 gesetzt ist (Lowbyte von x!) breq .L2 // springt nach L2 wenn R24 null ist ldi r24,lo8(17) // tmp=0x1111 ldi r25,hi8(17) std Y+2,r25 // tmp ist in Y+1 und Y*2 gespeichert std Y+1,r24 rjmp .L3 .L2: ldi r24,lo8(34) // tmp=0x2222 ldi r25,hi8(34) std Y+2,r25 std Y+1,r24 .L3: .LM3: ldd r24,Y+3 ldd r25,Y+4 andi r24,lo8(1) andi r25,hi8(1) cp __zero_reg__,r24 // Vergleicht Lowbyte von x mit null cpc __zero_reg__,r25 // dito Highbyte mit Carry! (beide Bytes werden ausgewertet) brge .L4 // Sprung wenn beide Vergleiche null sind ldi r24,lo8(51) ldi r25,hi8(51) std Y+2,r25 std Y+1,r24 rjmp .L5 .L4: ldi r24,lo8(68) ldi r25,hi8(68) std Y+2,r25 std Y+1,r24 .L5: // while(1) rjmp .L5
"Conditional relative branch. Tests the Zero Flag (Z) and branches relatively to PC if Z is set." Bedingter relativer Sprung, springt relativ zum Progammcounter, wenn ZeroFlag gesetzt ist. Das Z-Flag wird von tst gesetzt:
Z: R7• R6 •R5• R4• R3 •R2• R1• R0
Set if the result is $00; cleared otherwise.
Das ist aber das Ergebniss vom Test mit R24, wo wird geprüft, ob R25 auch null ist? Sehr seltsam.
btw. wird sowohl while(1) wie auch while(1==1) gleich übersetzt:
.L5:
rjmp .L5
Gruß
mic
[Edit]
tst scheint doch richtig zu funktionieren. Bei if(IsBitSet(x,0)) ergibt (1<<0) genau 1, das passt in das Lowbyte. Bei if(IsBitSet(x,15)) übersetzt der Kompiler so:
Genial ;)Code:29 .LM2: 30 000c 8B81 ldd r24,Y+3 31 000e 9C81 ldd r25,Y+4 32 0010 9923 tst r25 33 0012 04F4 brge .L2 34 0014 81E1 ldi r24,lo8(17) 35 0016 90E0 ldi r25,hi8(17) 36 0018 9A83 std Y+2,r25 37 001a 8983 std Y+1,r24 38 001c 00C0 rjmp .L3 39 .L2: 40 001e 82E2 ldi r24,lo8(34) 41 0020 90E0 ldi r25,hi8(34) 42 0022 9A83 std Y+2,r25 43 0024 8983 std Y+1,r24 44 .L3: 45 .LM3: 46 0026 8B81 ldd r24,Y+3 47 0028 9C81 ldd r25,Y+4 48 002a 8070 andi r24,lo8(-32768) 49 002c 9078 andi r25,hi8(-32768) 50 002e 1816 cp __zero_reg__,r24 51 0030 1906 cpc __zero_reg__,r25 52 0032 04F4 brge .L4 53 0034 83E3 ldi r24,lo8(51) 54 0036 90E0 ldi r25,hi8(51) 55 0038 9A83 std Y+2,r25 56 003a 8983 std Y+1,r24 57 003c 00C0 rjmp .L5 58 .L4: 59 003e 84E4 ldi r24,lo8(68) 60 0040 90E0 ldi r25,hi8(68) 61 0042 9A83 std Y+2,r25 62 0044 8983 std Y+1,r24 63 .L5: 64 0046 00C0 rjmp .L5
[EDIT2]
Erstaunlich was der Kompiler alles beachtet:
Code:#define IsBitSet(ADDR,BIT) (((ADDR) & (1<<BIT))?1:0) // Fragt Bit = 1? int main(void) { int x, tmp; if(IsBitSet(x,0)) tmp=11; else tmp=22; if(IsBitSet(x,15)) tmp=33; else tmp=44; while(1); return(0); }Code:.LM2: ldd r24,Y+3 ldd r25,Y+4 andi r24,lo8(1) andi r25,hi8(1) tst r24 breq .L2 ldi r24,lo8(11) ldi r25,hi8(11) std Y+2,r25 std Y+1,r24 rjmp .L3 .L2: ldi r24,lo8(22) ldi r25,hi8(22) std Y+2,r25 std Y+1,r24 .L3: .LM3: ldd r24,Y+3 ldd r25,Y+4 tst r25 brge .L4 ldi r24,lo8(33) ldi r25,hi8(33) std Y+2,r25 std Y+1,r24 rjmp .L5 .L4: ldi r24,lo8(44) ldi r25,hi8(44) std Y+2,r25 std Y+1,r24 .L5: rjmp .L5







Zitieren

Lesezeichen