Главная страница
Библиотека (скачать книги)
Скачать софт
Введение в программирование
Стандарты для C++
Уроки по C#
Уроки по Python
HTML
Веб-дизайн
Ассемблер в среде Windows
ActiveX
Javascript
Общее о Линукс
Линукс - подробно
Линукс - новое
Delphi
Паскаль для начинающих
Турбопаскаль
Новости
Партнеры
Наши предложения
Архив новостей





Теперь попробуем немного расшифровать данные. Первое слово в первой информационной строке, как мы выяснили, равно $С03А. Если мы возьмем фирменное описание команд, то обнаружим, что значению старшей тетрады в КОП, равной $С (1100 в двоичной системе), соответствует команда rjmp — как мы далее увидим, практически любая программа начинается с безусловного перехода на метку RESET. Теперь очевидно, что остальные биты в этом значении ($03А) представляют абсолютный адрес в программе, где в тексте ее стояла метка RESET. Попробуем его найти — для этого вспомним, что адреса отсчитываются по словам, а не по байтам, т. е. число $ЗА (58) нужно умножить на 2 (получится 116 = $74) и искать в этой области.
Разыщем строку с адресом $0070, отсчитаем три пары байтов от начала данных, и найдем там фрагмент "F894", который в нормальной записи-будет выглядеть, как $94F8, а это, как легко убедиться по справочнику, есть код команды cli, запрещающей прерывания (которая в начале программы лишняя, т. к. они все равно запрещены, но, видимо, поставлена на всякий случай). Следующая команда будет начинаться с байта $Е5, и первая тетрада в ней обозначает код команды ldi (1110— проверьте!), а пятерка, очевидно, есть фрагмент адреса конца памяти (RAMEND), который в силу довольно сложного формата записи команды получается на самом деле равным $025F (см. значение младшего байта, равное $2F). Это соответствует значению RAMEND, определенному в inc-файлах для МК с 512 байтами встроенного ОЗУ ($025F = 607, т. е. всего адресов 608, из которых 96 ($5F) занимают регистры, итого получается 512 ($0200) незанятых байтовых ячеек, составляющих ОЗУ).
Все, как и должно быть — если мы обратим внимание опять на первую-вторую строки с данными, то увидим повторяющийся фрагмент "1895", который, как легко догадаться из материала следующего раздела, должен быть командой reti— если проверите по справочнику, то так оно и окажется.

Как видите, разобраться довольно сложно, но при некотором навыке и наличии под рукой таблицы двоичных кодов команд вполне можно. Именно так работает программа, которая превращает код обратно в текст — дизассемблер (он входит в AVR Studio). Впрочем, в дизассемблированной программе разобраться бывает еще сложнее, чем в самом hex-файле, т. к. там, естественно, нет никаких меток и определений, все в абсолютных числах. А зачем это может понадобиться на практике?
Дело в том, что в памяти программ часто хранят константы — те, что предположительно не будут изменяться в процессе эксплуатации, например, устанавливаемые по умолчанию значения какой-то величины. Но, разумеется, по истечении некоторого времени или при переносе на другое устройство эти константы обязательно захочется изменить. Й если у вас текст программы по каким-то причинам отсутствует (например, программа взята из публикации в журнале или скачана с радиолюбительского сайта), а загрузочный hex-файл имеется, то всегда можно "хакнуть" исходный код и немного подправить его под свои нужды.

Команды, инструкции и нотация AVR-ассемблера
Для начала отметим, что все последующее изложение рассчитано на использование avrasm32, т. к. более "продвинутый" avrasm2 (с поддержкой большего количества разновидностей МК) имеет, к примеру, заметно отличающийся набор директив компилятора. Еще больше отличается нотация программ для ассемблеров сторонних производителей (той же IAR Systems). Разбираться в этих тонкостях — только путаться, поэтому мы ограничимся avrasm32.

Особенности мнемонической записи большинства команд в AVR-ассемблере такие же, как и в любых других ассемблерах. Сначала идет собственно команда (в AVR команды бывают двух-, трех-, и четырехбуквенные), затем через пробел или знак табуляции (этих знаков может быть в принципе любое количество больше нуля) следуют операнды. Некоторые команды операндов не имеют (lpm, reti), в других один операнд (inc г1б). Если команда имеет два операнда, то сначала указывают приемник, затем источник (это т. н. "прямая польская запись"). Между приемником и источником обязательно должна стоять запятая (с любым числом пробелов до или после нее, или вообще без них). Так, выражение sub ri6,ri7 означает, что из содержимого г1б нужно вычесть содержимое г!7, а результат окажется в г!б.

Общее правило для использования пробелов и знаков табуляции такое: нельзя разбивать идентификатор на части и, наоборот, нельзя сливать разные идентификаторы между собой — хотя бы один пробел, знак табуляции (или знак препинания, если это предусмотрено форматом команды) между наименованиями инструкций, переменных, регистров и т. п. должен быть.

Сразу заметим, что А VR-ассемблер регистр буке не различает, в том числе и в присвоенных программистом именах переменных, констант, меток и т. п. (одинаково правильной будет форма записи Jmp, JMP и jmp, так же как Reset, RESET И reset).

Каждая команда должна занимать отдельную строку (в большинстве языков высокого уровня операторы можно записывать в одной строке, например, разделяя их знаками препинания — здесь это не допускается). Разбивать команду на части разрывом строки нельзя. Кроме команды, единая строка может содержать метки и примечания.
Метка (label)— идентификатор произвольной длины, придуманный программистом и заканчивающийся двоеточием без пробела перед ним (metka:). Метку можно располагать и в отдельной строке. Кроме простого указания на адрес перехода для команд ветвления, метки служат также указанием на адрес подпрограмм (процедур) и заодно являются их именем.



     
 

Библиотека программиста. 2009.
Администратор: admin@programmer-lib.ru