I was taking a look at the disassembly for a loop of mine that seemed to be taking too long and I found these assembly instructions that I don't understand. Why does it load 0
into r25
and then do two adc r25, 25
instructions (which wouldn't do anything since r25
is 0
). This is for an ATTiny84 by the way.
EDIT: In general I'm confused about why there are so many instructions required to set DDRA, DDRB, PORTA, and PORTB in the last loop. I feel like an LD
to read portOuts[j], OUT
to output, and increment of j should be all that's required. I've tried to separate what I think is the relevant part in the disassembly.
void loop() {
set_sleep_mode(SLEEP_MODE_IDLE);
button = false;
DDRA = 0;
DDRB = 0;
PORTA = 255;
PORTB = 255;
do {
sleep_mode();
} while (!button);
// int digits[4];
// getTime(digits);
//
// long lights = calcDisp(digits);
static const byte highLow[28][2] = {{2, 0}, {2, 1}, {0, 3}, {1, 3}, {1, 0}, {3, 1}, {0, 1},
{0, 2}, {3, 0}, {2, 4}, {3, 4}, {4, 3}, {0, 4}, {4, 0},
{4, 1}, {1, 4}, {1, 5}, {5, 1}, {1, 2}, {5, 3}, {2, 3},
{2, 5}, {5, 2}, {5, 4}, {4, 5}, {3, 5}, {4, 2}, {3, 2}};
byte portOuts[112];
byte nLed = 0;
long lights = 0b00000000000000001111111111111111; // just a constant, for now
for (byte b = 0; b < 16; ++b) {
if (bitRead(lights, b)) {
byte high = highLow[b][0];
byte low = highLow[b][1];
byte highA = regs[high][0];
byte highB = regs[high][1];
byte lowA = regs[low][0];
byte lowB = regs[low][1];
portOuts[4 * nLed] = (highA)|(lowA);
portOuts[4 * nLed + 1] = (highB)|(lowB);
portOuts[4 * nLed + 2] = (highA)|(1<<PA6);
portOuts[4 * nLed + 3] = (highB);
++nLed;
}
}
for (byte i = 0; i < 200; ++i) {
for (byte j = 0; j < nLed * 4;) {
DDRA = portOuts[j++];
DDRB = portOuts[j++];
PORTA = portOuts[j++];
PORTB = portOuts[j++];
}
}
DISASSEMBLY
void loop() {
set_sleep_mode(SLEEP_MODE_IDLE);
button = false;
DDRA = 0;
DDRB = 0;
PORTA = 255;
228: bb 24 eor r11, r11
22a: ba 94 dec r11
{2, 5}, {5, 2}, {5, 4}, {4, 5}, {3, 5}, {4, 2}, {3, 2}};
byte portOuts[112];
byte nLed = 0;
long lights = 0b00000000000000001111111111111111; // just a constant, for now
for (byte b = 0; b < 16; ++b) {
if (bitRead(lights, b)) {
22c: cc 24 eor r12, r12
22e: ca 94 dec r12
230: dc 2c mov r13, r12
232: e1 2c mov r14, r1
234: f1 2c mov r15, r1
}
return lights;
}
void loop() {
set_sleep_mode(SLEEP_MODE_IDLE);
236: 85 b7 in r24, 0x35 ; 53
238: 87 7e andi r24, 0xE7 ; 231
23a: 85 bf out 0x35, r24 ; 53
button = false;
23c: 10 92 a6 00 sts 0x00A6, r1 ; 0x8000a6 <button>
DDRA = 0;
240: 1a ba out 0x1a, r1 ; 26
DDRB = 0;
242: 17 ba out 0x17, r1 ; 23
PORTA = 255;
244: bb ba out 0x1b, r11 ; 27
PORTB = 255;
246: b8 ba out 0x18, r11 ; 24
do {
sleep_mode();
248: 85 b7 in r24, 0x35 ; 53
24a: 80 62 ori r24, 0x20 ; 32
24c: 85 bf out 0x35, r24 ; 53
24e: 88 95 sleep
250: 85 b7 in r24, 0x35 ; 53
252: 8f 7d andi r24, 0xDF ; 223
254: 85 bf out 0x35, r24 ; 53
} while (!button);
256: 80 91 a6 00 lds r24, 0x00A6 ; 0x8000a6 <button>
25a: 88 23 and r24, r24
25c: a9 f3 breq .-22 ; 0x248 <main+0xec>
25e: ac e6 ldi r26, 0x6C ; 108
260: b0 e0 ldi r27, 0x00 ; 0
262: 90 e0 ldi r25, 0x00 ; 0
264: 80 e0 ldi r24, 0x00 ; 0
static const byte highLow[28][2] = {{2, 0}, {2, 1}, {0, 3}, {1, 3}, {1, 0}, {3, 1}, {0, 1},
{0, 2}, {3, 0}, {2, 4}, {3, 4}, {4, 3}, {0, 4}, {4, 0},
{4, 1}, {1, 4}, {1, 5}, {5, 1}, {1, 2}, {5, 3}, {2, 3},
{2, 5}, {5, 2}, {5, 4}, {4, 5}, {3, 5}, {4, 2}, {3, 2}};
byte portOuts[112];
byte nLed = 0;
266: 60 e0 ldi r22, 0x00 ; 0
268: 30 e0 ldi r19, 0x00 ; 0
26a: 20 e0 ldi r18, 0x00 ; 0
26c: a9 01 movw r20, r18
26e: 44 0f add r20, r20
270: 55 1f adc r21, r21
272: 44 0f add r20, r20
274: 55 1f adc r21, r21
long lights = 0b00000000000000001111111111111111; // just a constant, for now
for (byte b = 0; b < 16; ++b) {
if (bitRead(lights, b)) {
276: 26 01 movw r4, r12
278: 37 01 movw r6, r14
27a: 08 2e mov r0, r24
27c: 04 c0 rjmp .+8 ; 0x286 <__stack+0x27>
27e: 75 94 asr r7
280: 67 94 ror r6
282: 57 94 ror r5
284: 47 94 ror r4
286: 0a 94 dec r0
288: d2 f7 brpl .-12 ; 0x27e <__stack+0x1f>
28a: 40 fe sbrs r4, 0
28c: 3d c0 rjmp .+122 ; 0x308 <__stack+0xa9>
byte high = highLow[b][0];
byte low = highLow[b][1];
byte highA = regs[high][0];
28e: ec 91 ld r30, X
290: f0 e0 ldi r31, 0x00 ; 0
292: ee 0f add r30, r30
294: ff 1f adc r31, r31
296: e0 5a subi r30, 0xA0 ; 160
298: ff 4f sbci r31, 0xFF ; 255
29a: 70 81 ld r23, Z
byte highB = regs[high][1];
29c: a1 80 ldd r10, Z+1 ; 0x01
byte lowA = regs[low][0];
29e: 11 96 adiw r26, 0x01 ; 1
2a0: ec 91 ld r30, X
2a2: 11 97 sbiw r26, 0x01 ; 1
2a4: f0 e0 ldi r31, 0x00 ; 0
byte lowB = regs[low][1];
2a6: ee 0f add r30, r30
2a8: ff 1f adc r31, r31
2aa: e0 5a subi r30, 0xA0 ; 160
2ac: ff 4f sbci r31, 0xFF ; 255
2ae: 91 80 ldd r9, Z+1 ; 0x01
portOuts[4 * nLed] = (highA)|(lowA);
2b0: 21 e0 ldi r18, 0x01 ; 1
2b2: 30 e0 ldi r19, 0x00 ; 0
2b4: 2c 0f add r18, r28
2b6: 3d 1f adc r19, r29
2b8: 24 0f add r18, r20
2ba: 35 1f adc r19, r21
2bc: e0 81 ld r30, Z
2be: 7e 2e mov r7, r30
2c0: 77 2a or r7, r23
2c2: f9 01 movw r30, r18
2c4: 70 82 st Z, r7
portOuts[4 * nLed + 1] = (highB)|(lowB);
2c6: e2 e0 ldi r30, 0x02 ; 2
2c8: f0 e0 ldi r31, 0x00 ; 0
2ca: ec 0f add r30, r28
2cc: fd 1f adc r31, r29
2ce: e4 0f add r30, r20
2d0: f5 1f adc r31, r21
2d2: 2a 2d mov r18, r10
2d4: 29 29 or r18, r9
2d6: 20 83 st Z, r18
portOuts[4 * nLed + 2] = (highA)|(1<<PA6);
2d8: e3 e0 ldi r30, 0x03 ; 3
2da: f0 e0 ldi r31, 0x00 ; 0
2dc: ec 0f add r30, r28
2de: fd 1f adc r31, r29
2e0: e4 0f add r30, r20
2e2: f5 1f adc r31, r21
2e4: 70 64 ori r23, 0x40 ; 64
2e6: 70 83 st Z, r23
portOuts[4 * nLed + 3] = (highB);
2e8: 24 e0 ldi r18, 0x04 ; 4
2ea: 30 e0 ldi r19, 0x00 ; 0
2ec: 2c 0f add r18, r28
2ee: 3d 1f adc r19, r29
2f0: 42 0f add r20, r18
2f2: 53 1f adc r21, r19
2f4: fa 01 movw r30, r20
2f6: a0 82 st Z, r10
++nLed;
2f8: 6f 5f subi r22, 0xFF ; 255
2fa: 26 2f mov r18, r22
2fc: 30 e0 ldi r19, 0x00 ; 0
2fe: a9 01 movw r20, r18
300: 44 0f add r20, r20
302: 55 1f adc r21, r21
304: 44 0f add r20, r20
306: 55 1f adc r21, r21
308: 01 96 adiw r24, 0x01 ; 1
30a: 12 96 adiw r26, 0x02 ; 2
{4, 1}, {1, 4}, {1, 5}, {5, 1}, {1, 2}, {5, 3}, {2, 3},
{2, 5}, {5, 2}, {5, 4}, {4, 5}, {3, 5}, {4, 2}, {3, 2}};
byte portOuts[112];
byte nLed = 0;
long lights = 0b00000000000000001111111111111111; // just a constant, for now
for (byte b = 0; b < 16; ++b) {
30c: 80 31 cpi r24, 0x10 ; 16
30e: 91 05 cpc r25, r1
310: 09 f0 breq .+2 ; 0x314 <__stack+0xb5>
312: ac cf rjmp .-168 ; 0x26c <__stack+0xd>
314: 68 ec ldi r22, 0xC8 ; 200
portOuts[4 * nLed + 3] = (highB);
++nLed;
}
}
####################### START OF RELEVANT SECTION #############################
for (byte i = 0; i < 200; ++i) {
for (byte j = 0; j < nLed * 4;) {
316: 41 15 cp r20, r1
318: 51 05 cpc r21, r1
31a: 99 f1 breq .+102 ; 0x382 <__stack+0x123>
31c: 30 e0 ldi r19, 0x00 ; 0
31e: 20 e0 ldi r18, 0x00 ; 0
320: 80 e0 ldi r24, 0x00 ; 0
DDRA = portOuts[j++];
322: e1 e0 ldi r30, 0x01 ; 1
324: f0 e0 ldi r31, 0x00 ; 0
326: ec 0f add r30, r28
328: fd 1f adc r31, r29
32a: 2e 0f add r18, r30
32c: 3f 1f adc r19, r31
32e: f9 01 movw r30, r18
330: 90 81 ld r25, Z
332: 9a bb out 0x1a, r25 ; 26 STORE IN DDRA
334: e1 e0 ldi r30, 0x01 ; 1
336: e8 0f add r30, r24
DDRB = portOuts[j++];
338: 21 e0 ldi r18, 0x01 ; 1
33a: 30 e0 ldi r19, 0x00 ; 0
33c: 2c 0f add r18, r28
33e: 3d 1f adc r19, r29
340: 2e 0f add r18, r30
342: 31 1d adc r19, r1
344: f9 01 movw r30, r18
346: 90 81 ld r25, Z
348: 97 bb out 0x17, r25 ; 23 STORE IN DDRB
PORTA = portOuts[j++];
34a: e3 e0 ldi r30, 0x03 ; 3
34c: e8 0f add r30, r24
}
}
for (byte i = 0; i < 200; ++i) {
for (byte j = 0; j < nLed * 4;) {
DDRA = portOuts[j++];
DDRB = portOuts[j++];
34e: a2 e0 ldi r26, 0x02 ; 2
350: a8 0f add r26, r24
PORTA = portOuts[j++];
352: 21 e0 ldi r18, 0x01 ; 1
354: 30 e0 ldi r19, 0x00 ; 0
356: 2c 0f add r18, r28
358: 3d 1f adc r19, r29
35a: 2a 0f add r18, r26
35c: 31 1d adc r19, r1
35e: d9 01 movw r26, r18
360: 9c 91 ld r25, X
362: 9b bb out 0x1b, r25 ; 27 STORE IN PORTA
PORTB = portOuts[j++];
364: 8c 5f subi r24, 0xFC ; 252
366: 21 e0 ldi r18, 0x01 ; 1
368: 30 e0 ldi r19, 0x00 ; 0
36a: 2c 0f add r18, r28
36c: 3d 1f adc r19, r29
36e: 2e 0f add r18, r30
370: 31 1d adc r19, r1
372: f9 01 movw r30, r18
374: 90 81 ld r25, Z
376: 98 bb out 0x18, r25 ; 24 STORE IN PORTB
portOuts[4 * nLed + 3] = (highB);
++nLed;
}
}
for (byte i = 0; i < 200; ++i) {
for (byte j = 0; j < nLed * 4;) {
378: 28 2f mov r18, r24
37a: 30 e0 ldi r19, 0x00 ; 0
37c: 24 17 cp r18, r20
37e: 35 07 cpc r19, r21
380: 84 f2 brlt .-96 ; 0x322 <__stack+0xc3> JUMP BACK TO START OF LOOP
382: 61 50 subi r22, 0x01 ; 1
portOuts[4 * nLed + 2] = (highA)|(1<<PA6);
portOuts[4 * nLed + 3] = (highB);
++nLed;
}
}
for (byte i = 0; i < 200; ++i) {
384: 41 f6 brne .-112 ; 0x316 <__stack+0xb7>
setup();
for (;;) {
loop();
if (serialEventRun) serialEventRun();
386: 01 15 cp r16, r1
388: 11 05 cpc r17, r1
38a: 09 f4 brne .+2 ; 0x38e <__stack+0x12f>
38c: 54 cf rjmp .-344 ; 0x236 <main+0xda>
38e: 38 de rcall .-912 ; 0x0 <__vectors>
390: 52 cf rjmp .-348 ; 0x236 <main+0xda>```
which wouldn't do anything since r25 is 0
... not quite true ... think about whatadc
does – jsotola May 24 '20 at 16:0430e
afterr25
had been updated to a new value. In this case theldi r25,0
is just initializing the first pass and it would not be worth it to jump over the initial adds even though they dont do anything on that first pass. . – bigjosh May 24 '20 at 16:04r24
is coming into this block with a useful value, but that code is not shown. – bigjosh May 24 '20 at 16:09