Возник вопросик. Хочу уяснить для себя кое-что.
Компилятор: avr-gcc (WinAVR 20090313) 4.3.2.
Тест1 - размер структуры 7 байт и компилятор возвращает её через регистры - размер прошивки 60518 байт.
Код
typedef struct
{
unsigned char sec;
unsigned char min;
unsigned char hour;
unsigned char sec_div10; // десятые секунды.
unsigned char dat; // день месяца.
unsigned char month;
unsigned char year; // 0 = 2000
} rtc_t;
Тест2 - размер структуры 39 байт и компилятор возвращает её через стек??? - размер прошивки 60088 байт (значительно компактней!!!).
Код
typedef struct
{
unsigned char sec;
unsigned char min;
unsigned char hour;
unsigned char sec_div10; // десятые секунды.
unsigned char dat; // день месяца.
unsigned char month;
unsigned char year; // 0 = 2000
unsigned char dummy[32];
} rtc_t;
Исходник:
Код
//=============================================================================
rtc_t dffs_get_page_start_time(unsigned short page)
{
rtc_t rtc;
df_read_to(page, DFFS_RTC_OFFSET, sizeof(rtc_t), &rtc);
return (rtc);
}
Есть два вопроса. Прошу не пинать (я знаю что можно возвращать указатель) вопросы только для самообразования.
1. как работает механизм передачи больших структур (если при выходе из неё я вижу полную раскрутку стека обратно)?
2. как принудить компилятор возвращать структуры через стек (если это так, пока я не понял).
Листинг варианта1:
Код
//=============================================================================
rtc_t dffs_get_page_start_time(unsigned short page)
{
b488: 2f 92 push r2
b48a: 3f 92 push r3
b48c: 4f 92 push r4
b48e: 5f 92 push r5
b490: 6f 92 push r6
b492: 7f 92 push r7
b494: 8f 92 push r8
b496: 9f 92 push r9
b498: af 92 push r10
b49a: bf 92 push r11
b49c: cf 92 push r12
b49e: df 92 push r13
b4a0: ef 92 push r14
b4a2: ff 92 push r15
b4a4: 0f 93 push r16
b4a6: 1f 93 push r17
b4a8: df 93 push r29
b4aa: cf 93 push r28
b4ac: cd b7 in r28, 0x3d; 61
b4ae: de b7 in r29, 0x3e; 62
b4b0: 2e 97 sbiw r28, 0x0e; 14
b4b2: 0f b6 in r0, 0x3f; 63
b4b4: f8 94 cli
b4b6: de bf out 0x3e, r29; 62
b4b8: 0f be out 0x3f, r0; 63
b4ba: cd bf out 0x3d, r28; 61
rtc_t rtc;
df_read_to(page, DFFS_RTC_OFFSET, sizeof(rtc_t), &rtc);
b4bc: 63 e0 ldi r22, 0x03; 3
b4be: 70 e0 ldi r23, 0x00; 0
b4c0: 47 e0 ldi r20, 0x07; 7
b4c2: 8e 01 movw r16, r28
b4c4: 0f 5f subi r16, 0xFF; 255
b4c6: 1f 4f sbci r17, 0xFF; 255
b4c8: 98 01 movw r18, r16
b4ca: 0e 94 b2 29 call 0x5364; 0x5364 <df_read_to>
return (rtc);
b4ce: de 01 movw r26, r28
b4d0: 18 96 adiw r26, 0x08; 8
b4d2: f8 01 movw r30, r16
b4d4: 87 e0 ldi r24, 0x07; 7
b4d6: 01 90 ld r0, Z+
b4d8: 0d 92 st X+, r0
b4da: 81 50 subi r24, 0x01; 1
b4dc: e1 f7 brne .-8; 0xb4d6 <dffs_get_page_start_time+0x4e>
b4de: 8e 85 ldd r24, Y+14; 0x0e
b4e0: 99 24 eor r9, r9
b4e2: 28 84 ldd r2, Y+8; 0x08
b4e4: 39 84 ldd r3, Y+9; 0x09
b4e6: 4a 84 ldd r4, Y+10; 0x0a
b4e8: 5b 84 ldd r5, Y+11; 0x0b
b4ea: 6c 84 ldd r6, Y+12; 0x0c
b4ec: 7d 84 ldd r7, Y+13; 0x0d
b4ee: 51 01 movw r10, r2
b4f0: 62 01 movw r12, r4
b4f2: 73 01 movw r14, r6
}
b4f4: 95 01 movw r18, r10
b4f6: a6 01 movw r20, r12
b4f8: b7 01 movw r22, r14
b4fa: 99 2d mov r25, r9
b4fc: 2e 96 adiw r28, 0x0e; 14
b4fe: 0f b6 in r0, 0x3f; 63
b500: f8 94 cli
b502: de bf out 0x3e, r29; 62
b504: 0f be out 0x3f, r0; 63
b506: cd bf out 0x3d, r28; 61
b508: cf 91 pop r28
b50a: df 91 pop r29
b50c: 1f 91 pop r17
b50e: 0f 91 pop r16
b510: ff 90 pop r15
b512: ef 90 pop r14
b514: df 90 pop r13
b516: cf 90 pop r12
b518: bf 90 pop r11
b51a: af 90 pop r10
b51c: 9f 90 pop r9
b51e: 8f 90 pop r8
b520: 7f 90 pop r7
b522: 6f 90 pop r6
b524: 5f 90 pop r5
b526: 4f 90 pop r4
b528: 3f 90 pop r3
b52a: 2f 90 pop r2
b52c: 08 95 ret
Видно что он резервирует на стеке вдвое больше памяти чем надо (14 байт вместо 7) потом тупо копирует одно в другое (из одной половинки 14-и байтного участка памяти в другую), потом читает вторую область памяти во временные регистры, потом копирует их содержимое в нужные регистры. Короче мрачняк...
Листинг варианта2:
Код
//=============================================================================
rtc_t dffs_get_page_start_time(unsigned short page)
{
b476: ef 92 push r14
b478: ff 92 push r15
b47a: 0f 93 push r16
b47c: 1f 93 push r17
b47e: df 93 push r29
b480: cf 93 push r28
b482: cd b7 in r28, 0x3d; 61
b484: de b7 in r29, 0x3e; 62
b486: a7 97 sbiw r28, 0x27; 39
b488: 0f b6 in r0, 0x3f; 63
b48a: f8 94 cli
b48c: de bf out 0x3e, r29; 62
b48e: 0f be out 0x3f, r0; 63
b490: cd bf out 0x3d, r28; 61
b492: 7c 01 movw r14, r24
b494: cb 01 movw r24, r22
rtc_t rtc;
df_read_to(page, DFFS_RTC_OFFSET, sizeof(rtc_t), &rtc);
b496: 63 e0 ldi r22, 0x03; 3
b498: 70 e0 ldi r23, 0x00; 0
b49a: 47 e2 ldi r20, 0x27; 39
b49c: 8e 01 movw r16, r28
b49e: 0f 5f subi r16, 0xFF; 255
b4a0: 1f 4f sbci r17, 0xFF; 255
b4a2: 98 01 movw r18, r16
b4a4: 0e 94 b2 29 call 0x5364; 0x5364 <df_read_to>
return (rtc);
b4a8: d7 01 movw r26, r14
b4aa: f8 01 movw r30, r16
b4ac: 87 e2 ldi r24, 0x27; 39
b4ae: 01 90 ld r0, Z+
b4b0: 0d 92 st X+, r0
b4b2: 81 50 subi r24, 0x01; 1
b4b4: e1 f7 brne .-8; 0xb4ae <dffs_get_page_start_time+0x38>
}
b4b6: c7 01 movw r24, r14
b4b8: a7 96 adiw r28, 0x27; 39
b4ba: 0f b6 in r0, 0x3f; 63
b4bc: f8 94 cli
b4be: de bf out 0x3e, r29; 62
b4c0: 0f be out 0x3f, r0; 63
b4c2: cd bf out 0x3d, r28; 61
b4c4: cf 91 pop r28
b4c6: df 91 pop r29
b4c8: 1f 91 pop r17
b4ca: 0f 91 pop r16
b4cc: ff 90 pop r15
b4ce: ef 90 pop r14
b4d0: 08 95 ret
Тут всё красиво, но не понимаю как оно работает!!!
Прошу прощения за длинное сообщение - не понял как создать окошко со скроллером.
И ещё, никогда не пробовал, так и не знал, что можно присваивать структуру структуре

Код
rtc_t rtc1 = {0};
rtc_t rtc2;
....
rtc1 = rtc2; // и без всяких memcpy (здорово, код получается компактный с однобайтным счётчиком цикла!)