Я нашел ответ!
Я собирал, но не связывал. Таким образом, ассемблер заполнял все относительные переходы / вызовы / ответвления с помощью. + 0.
Чтобы исправить это, мне нужно было создать собственный скрипт компоновщика, который я назвал linker.x, который содержит следующее:
SECTIONS
{
. = 0x0;
.text : { *(.text) }
}
Это говорит компоновщику начать секцию .text по адресу 0.
Тогда я мог бы связать код, используя:
$ avr-ld -mavr4 -Tlinker.x a.out -o output.o
После связывания с помощью вышеуказанной команды все + 0 были заполнены правильными значениями!
Причина этого в том, что до стадии связывания, поскольку / gcc не знает, что еще будет включено в двоичный файл. Это компоновщик, который берет все отдельные объектные файлы и объединяет их в один. Поэтому, если стадия компоновщика никогда не запускается, невозможно заполнить относительные переходы абсолютными переходами.
Ассемблер AVR выполняет сборку и связывание. Но ассемблер gnu более универсален, и поэтому вам нужно ссылаться отдельно.