avr-gcc: Итерация по массиву символов не работает при слишком большом количестве итераций.

У меня есть простая функция, которая перебирает массив символов и вызывает функцию с каждым символом.

void loopFunction(void)                                                                                                                                               
{
    char *mystring = "ABCDEF";
    int i = 0;
    for (i = 0; i<3; i++) {
        LCD_Write(mystring[i]);
    }
}

Эта функция отлично работает, выдавая правильный вывод (в конце концов, на моем ЖК-дисплее), и промежуточный ассемблерный код выглядит нормально:

loopFunction:
/* prologue: function */
/* frame size = 0 */
/* stack size = 0 */
.L__stack_usage = 0 
    ldi r24,lo8(65)
    call LCD_Write
    ldi r24,lo8(66)
    call LCD_Write
    ldi r24,lo8(67)
    jmp LCD_Write
    .size   loopFunction, .-loopFunction  

Как мы видим, цикл превратился в простой вызов функции три раза.

Теперь проблема начинается, когда я хочу выполнить цикл 4 раза:

void loopFunction(void)                                                                                                                                               
{
    char *mystring = "ABCDEF";
    int i = 0;
    for (i = 0; i<4; i++) {
        LCD_Write(mystring[i]);
    }
}


loopFunction:
    push r28
    push r29
/* prologue: function */
/* frame size = 0 */
/* stack size = 2 */
.L__stack_usage = 2
    ldi r28,lo8(.LC0)
    ldi r29,hi8(.LC0)
.L12:
    ld r24,Y+
    call LCD_Write
    ldi r24,hi8(.LC0+4)
    cpi r28,lo8(.LC0+4)
    cpc r29,r24
    brne .L12
/* epilogue start */                                                                                                                                                      
    pop r29
    pop r28
    ret

Итак, мне кажется, что к фактически сохраненной строке никогда не обращаются

.LC0:
    .string "ABCDEF"
    .text

Что я делаю не так?

Я звоню avr-gcc

avr-gcc -mmcu=atmega16 -Wall -O3 --save-temps -Os -c lcd.c

на Debian10 с пакетами из репозитория buster

  • avr-gcc версия 5.4.0
  • avr-libc 2.0.0+Atmel3.6.1-2

person mrleop    schedule 23.03.2020    source источник


Ответы (1)


Доступ к сохраненной строке осуществляется в той части ассемблерного кода, которая говорит Y+.

Этот фрагмент кода означает чтение из указателя Y, а затем увеличение указателя. Указатель Y хранится в регистрах r29 и r28. Первые две инструкции ldi в вашей сборке устанавливают указатель Y на начало сохраненной строки.

person David Grayson    schedule 24.03.2020