Как я могу перейти относительно ПК, используя ассемблер gnu для AVR?
-
21-09-2019 - |
Вопрос
У меня есть двоичный файл, который я дизассемблировал с помощью avr-objcopy.Таблица векторов прерываний выглядит следующим образом:
00000000 : ; VECTOR TABLE 0: 13 c0 rjmp .+38 ; 0x28, RESET 2: b8 c1 rjmp .+880 ; 0x374, INT0 4: fd cf rjmp .-6 ; 0x0 6: fc cf rjmp .-8 ; 0x0 8: fb cf rjmp .-10 ; 0x0 a: fa cf rjmp .-12 ; 0x0 c: f9 cf rjmp .-14 ; 0x0 e: f8 cf rjmp .-16 ; 0x0 10: f7 cf rjmp .-18 ; 0x0 12: c7 c1 rjmp .+910 ; 0x3a2, TIMER1 OVF 14: f5 cf rjmp .-22 ; 0x0 16: f4 cf rjmp .-24 ; 0x0 18: f3 cf rjmp .-26 ; 0x0 1a: f2 cf rjmp .-28 ; 0x0 1c: 2b c2 rjmp .+1110 ; 0x474, ADC conversion complete 1e: f0 cf rjmp .-32 ; 0x0 20: ef cf rjmp .-34 ; 0x0 22: ee cf rjmp .-36 ; 0x0 24: ed cf rjmp .-38 ; 0x0 26: 00 00 nop ; START 28: f8 94 cli (snip)
Я хочу собрать этот файл заново с несколькими изменениями.Я переформатировал его, удалив первые 2 столбца, чтобы это был обычный файл сборки.ie:
.org 0 rjmp .+38 ; 0x28, RESET rjmp .+880 ; 0x374, INT0 (snip)
Однако, когда я запускаю
$ avr-as -mmcu=atmega8 test.asm
а затем разберите сгенерированный файл.(используя objcopy -S a.out) Вывод выглядит следующим образом:
00000000 : 0: 00 c0 rjmp .+0 ; 0x2 2: 00 c0 rjmp .+0 ; 0x4 4: 00 c0 rjmp .+0 ; 0x6 6: 00 c0 rjmp .+0 ; 0x8 8: 00 c0 rjmp .+0 ; 0xa a: 00 c0 rjmp .+0 ; 0xc c: 00 c0 rjmp .+0 ; 0xe e: 00 c0 rjmp .+0 ; 0x10 10: 00 c0 rjmp .+0 ; 0x12 12: 00 c0 rjmp .+0 ; 0x14 14: 00 c0 rjmp .+0 ; 0x16 16: 00 c0 rjmp .+0 ; 0x18 18: 00 c0 rjmp .+0 ; 0x1a 1a: 00 c0 rjmp .+0 ; 0x1c 1c: 00 c0 rjmp .+0 ; 0x1e 1e: 00 c0 rjmp .+0 ; 0x20 20: 00 c0 rjmp .+0 ; 0x22 22: 00 c0 rjmp .+0 ; 0x24 24: 00 c0 rjmp .+0 ; 0x26 26: 00 00 nop 28: f8 94 cli (snip)
Итак, как я могу заставить avr-as учитывать скачки относительно ПК?
Решение
Я нашел ответ!
Я собирал, но не связывал.Таким образом, ассемблер заполнял все относительные переходы / вызовы / ответвления значением .+0.
Чтобы исправить это, мне нужно было создать пользовательский скрипт компоновщика, который я назвал linker.x, который содержит следующее:
SECTIONS { . = 0x0; .text : { *(.text) } }
Это указывает компоновщику запустить раздел .text по адресу 0.
Тогда я мог бы связать код, используя:
$ avr-ld -mavr4 -Tlinker.x a.out -o output.o
После связывания с помощью приведенной выше команды все .+ 0 были заполнены их правильными значениями!
Причина этого заключается в том, что до этапа компоновки as / gcc не знает, что еще будет включено в двоичный файл.Это компоновщик, который берет все отдельные объектные файлы и объединяет их в один.Таким образом, если этап компоновки никогда не запускается, нет способа заполнить относительные переходы абсолютными переходами.
Ассемблер AVR выполняет как сборку, так и компоновку.Но ассемблер gnu является более универсальным, и поэтому вам нужно ссылаться отдельно.
Другие советы
Я предполагаю, что rjmp PC+2
не работает в avr-as ?Вот как я бы сделал это в AVR Studio...