Директива Avra .db, похоже, не работает должным образом

#assembly #atmega #atmega16

#сборка #atmega #atmega16

Вопрос:

Я пытаюсь написать некоторый код для ATmega16. Я использую avra (версия 1.4.2) под FreeBSD 12.2-RELEASE. В моем сегменте кода у меня есть следующее:

 helloStr:   .db "Hello World"
 

Насколько я понимаю, байты символов должны быть непрерывными.
Однако, когда я смотрю на созданный объектный файл, я вижу следующее (я собираю код с помощью команды avra main.asm):

 00000190: 0000 3600 0000 2a65 4800 0039 0000 002b  ..6...*eH..9...                                                     
000001a0: 6c6c 0000 3900 0000 2c20 6f00 0039 0000  ll..9..., o..9..                                                    
000001b0: 002d 6f57 0000 3900 0000 2e6c 7200 0039  .-oW..9....lr..9                                                    
000001c0: 0000 002f 5c64 0000 3900 0000 3000 3000  .../d..9...0.0.                                                    
000001d0: 0039 0000 0031 e2fa 0000 3d00 0000 32e0  .9...1....=...2.
 

Обратите внимание справа, что символы не являются последовательными.
Я смотрю на файл .obj, который создает avra.
Когда я пытаюсь запустить код, он, похоже, подтверждает мои предположения о том, что символьные байты не хранятся последовательно, поскольку я получаю в основном мусор на дисплее с некоторыми правильными символами, но разнесенными слишком далеко друг от друга.
Я не думаю, что что-то не так с моей процедурой отображения (код ЖК-дисплея будет отображать символ правильно, если я удалю код цикла и сохраню символ непосредственно в r16, используя ldi r16, ‘H’, например.):

 WRITE_TO_LCD:
    push    r16
    push    r17
START_WRITE_TO_LCD:

    lpm r16, Z 
    
    ldi r17, 0b0
    cp  r16, r17        ; Have we hit the null byte?
    breq    END_WRITE_TO_LCD
    ;; Output character command.
    out PortA, r16
    ldi r16, low(registerSelect)    ; Set RS control signal
    out PortC, r16
    ;; Set E and RS control siginals.
    ldi r16, (low(registerSelect) | low(enable))
    out PortC, r16
    ldi r16, low(registerSelect)    ; Clear E control signal
    out PortC, r16
    jmp START_WRITE_TO_LCD
END_WRITE_TO_LCD:
    pop r17
    pop r16
    ret
 

Я загружаю Z с:

     ldi r31, low(helloStr)
    ldi r30, high(helloStr)
 

прежде чем я вызову WRITE_TO_LCD . Я не уверен, что низкий уровень до r31 и высокий до r30 — это правильный путь, но я также пробовал другой способ. Я также читал, что память адресуется с использованием 2-байтовых слов, поэтому я должен использовать 2 * helloStr. Я тоже пытался это сделать. Возможно, эти детали, которые я только что упомянул, неверны в коде, который я показал здесь, но я перепробовал все перестановки, и я не думаю, что это проблема (о чем свидетельствует вывод, выведенный на ЖК-дисплей, и то, что я вижу в шестнадцатеричном редакторе).

Также у меня есть define helloStr после моего вектора прерывания. Если я помещу ее перед вектором прерывания, я, похоже, не вижу никаких доказательств этого в файле .obj, и вывод на ЖК-дисплей отличается, когда я его запускаю. Я предполагаю, что это как-то связано с тем, что вектор прерывания должен быть первым в памяти или что-то в этом роде. Но я бы подумал, что это все равно появилось бы в коде, и обработка прерываний была бы испорчена.

В любом случае, что меня действительно интересует, так это получение непрерывной строки во flash, чтобы я мог перебирать ее в цикле.

Если у кого-нибудь есть какие-либо идеи, что я могу делать неправильно, я был бы очень признателен за ваш вклад.

Комментарии:

1. По-видимому, это особенность формата объектного файла. Я просто помещаю вашу строку в файл самостоятельно и вижу то же самое. Однако avra сообщает «Код: 7 слов (14 байт)» , что верно, и hex файл также правильный. Как вы создаете окончательное изображение? Вы заглядывали внутрь этого с помощью шестнадцатеричного редактора?

2. Когда я запускаю команду avra main.asm, она создает следующие файлы: main.eep.hex, main.hex и main.obj. Я записываю main.hex в микро, используя avrdude. Причина, по которой я не просматривал шестнадцатеричный файл, заключается в том, что это ascii-представление шестнадцатеричного кода, и сложнее понять, что происходит с точки зрения строки. Я думаю, теперь, когда я думаю об этом, не должно потребоваться слишком много времени, чтобы проверить это таким образом. Однако в моем коде все еще должно быть что-то не так:'(ха-ха. Также спасибо за ваш ответ.

3. Да, вы должны использовать 2*helloStr и убедитесь, что вы ввели младший байт r30 (ваш код перевернут).

4. Ваше право. Я не имею в виду, что я вам не поверил. Я просто вложил это в этот удобный прицел: binaryhexconverter.com/hex-to-ascii-text-converter Я предполагаю, что тогда должно быть что-то не так с тем, как я обращаюсь к строке. Я потратил немало времени, пытаясь заставить ее работать. Так что я не совсем уверен, в чем может быть проблема.

5. Это исправило это! Большое спасибо. Я чувствую себя глупо, ха-ха. Клянусь, я пробовал это. Тем не менее, в коде, который я опубликовал, все еще есть пара ошибок. Похоже, что после установки enable требуется некоторое количество nop (я использую micro на частоте 1 МГц, а ЖК-дисплей — 1602A), а также я не думаю, что ассемблер превращает в нулевой байт. В любом случае это работает :).