Содержание
Директивы ассемблера, “шапка” программы | RadioLaba.ru
- admin
- 20.12.2013
- Программирование PIC-контроллеров
“Шапка” программы начинается с подключения специального файла с расширением INC, в виде строчки #include , где include – директива подключения дополнительного файла. Эти файлы для каждого типа микроконтроллера хранятся в папке программы MPLAB. В этих файлах адресам регистров специального назначения присвоены их названия, а также названия битов, это сделано для удобного написания программы. Если этот файл не подключать, то придется вручную присваивать соответствующие названия, иначе MPLAB выдаст ошибки.
Далее идет строчка с указанием типа микроконтроллера в виде директивы LIST p=16F628A. После нее строчка __CONFIG 3F01h ( __CONFIG – директива установки битов конфигурации), здесь двухбайтным шестнадцатеричным числом 3F01h (значение слова конфигурации) настраиваются биты конфигурации микроконтроллера (выбор кварцевого генератора, сторожевой таймер, защита памяти программ и др. ). Для лучшей наглядности при настройке битов можно прописать значение слова конфигурации в двоичной форме __CONFIG b’11111100000001′.
Теперь необходимо присвоить названия адресам регистров ОЗУ, которые будут использоваться в программе. Делается это для удобного написания программы. Присвоение название осуществляется директивой equ (определение константы), например, var equ 0020h. Записи var в этом случае будет соответствовать число 0020h, которое является адресом регистра ОЗУ в памяти данных, кстати, в файле P16F628A.INC названия регистрам специального назначения присвоены таким же образом.
Я также использую директиву #define (определение текстовой последовательности для замены), чтобы присвоить названия линиям порта микроконтроллера. Например, строка #define led PORTВ,0 означает что, запись led будет заменяться на PORTB,0. Составляя текст программы не надо везде писать PORTB,0, а пишем просто led.
Все вышесказанное относится к “шапке” программы, после которой следует сам текст программы. Директивой org (определение начального адреса) задают начальный адрес в памяти программ, после которого будет располагаться код программы. Строка org 0000h означает что, код программы расположиться, начиная с 0-го адреса памяти программ. Подпрограмма обработчика прерываний должна располагаться, начиная с адреса 0004h, поэтому в начале подпрограммы необходимо написать строку org 0004h, при этом до этой строки надо написать org 0000h и команду перехода GOTO на основную программу, иначе исполнение основной программы начнется с подпрограммы обработчика прерываний. Если прерывания не задействованы, можно не пользоваться директивой org, программа автоматически расположиться с нулевого адреса памяти программ. Вообще с помощью этой директивы можно расположить требуемый участок кода в любую область памяти программ.
Директива end в конце программы указывает на окончание программы, конец всех команд.
Таким образом, шапка программы выглядит примерно следующим образом:
#include <P16F628A. INC> ;подключение файла P16F628A.INC
LIST p=16F628A ;указание типа процессора
__CONFIG 3F18h ;установка битов конфигурации
Sec equ 0020h ;присвоение названий регистрам ОЗУ
Sec0 equ 0021h
Sec1 equ 0022h
var equ 0023h
T1L equ 0024h
T1H equ 0025h
shet equ 0026h
W_temp equ 0079h
STATUS_temp equ 007Ah
#define led PORTA,7 ;присвоение названий линиям порта
#define knp1 PORTB,0
#define knp2 PORTB,1
#define signal PORTB,2
org 0000h ;начать выполнение программы с адреса 0000h
goto Start ;переход на метку Start
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;Подпрограмма обработки прерываний
org 0004h ;начать выполнение подпрограммы с адреса 0004h
. ……………. ;тело подпрограммы
……………..
……………..
retfie ;выход из подпрограммы прерывания
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;Основная программа
Start …………….. ;тело основной программы
……………..
……………..
end ;конец всей программы
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 |
#include <P16F628A. INC> ;подключение файла P16F628A.INC LIST p=16F628A ;указание типа процессора __CONFIG 3F18h ;установка битов конфигурации
Sec equ 0020h ;присвоение названий регистрам ОЗУ Sec0 equ 0021h Sec1 equ 0022h var equ 0023h T1L equ 0024h T1H equ 0025h shet equ 0026h W_temp equ 0079h STATUS_temp equ 007Ah
#define led PORTA,7 ;присвоение названий линиям порта #define knp1 PORTB,0 #define knp2 PORTB,1 #define signal PORTB,2
org 0000h ;начать выполнение программы с адреса 0000h goto Start ;переход на метку Start
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;Подпрограмма обработки прерываний
org 0004h ;начать выполнение подпрограммы с адреса 0004h
. ……………. ;тело подпрограммы …………….. ……………..
retfie ;выход из подпрограммы прерывания ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;Основная программа
Start …………….. ;тело основной программы …………….. ……………..
end ;конец всей программы |
Как видно здесь нет ничего сложного, далее остается только написать текст программы.
Tags: asm, PIC, директива, шапка
Программирование микроконтроллеров PIC. Часть 3. Структура программы на ассемблере — radiohlam.ru
Итак, давайте разберёмся, какую структуру имеет программа на языке ассемблер и для чего предназначены отдельные части программы.
Для дальнейшего чтения неплохо иметь под рукой текст какой-нибудь программы и документацию на контроллер (либо распечатку, либо просто открыть их в соседних окошках), чтобы можно было в процессе чтения находить в тексте программы и в документации то, о чём читаешь. Так информация лучше доходит и запоминается.
Ниже показана типичная структура программы на ассемблере.
|
||
|
1. Шапка программы.
В шапке указывается различная служебная информация для компилятора. То есть, практически всё, что находится в шапке, служит инструкциями не для контроллера, а для компилятора (кроме слова конфигурации).
list — директива, которая имеет кучу опций и может быть использована для управления процессом ассемблирования. Её можно и не использовать вовсе (настройки компилятор всё равно возьмёт из менеджера проекта), но указав этой директивой тип процессора, программа становится удобнее для восприятия. Во-первых, сразу видно для какого контроллера она написана. Во-вторых, если контроллер, указанный директивой list, не совпадает с контроллером, указанным в менеджере, то при компиляции будет сгенерирована ошибка (чтобы вы уже точно заметили, что программа написана под другой контроллер).
__config значение — эта директива указывает значение слова конфигурации контроллера. Слово конфигурации определяет основные параметры контроллера (какой будет использоваться генератор, будет ли установлена защита памяти программ и т.д.).
Поскольку каждый из параметров контроллера задаётся в слове конфигурации одним или несколькими битами, то это слово удобнее всего записывать в двоичной форме (для наглядности).
CBLOCK число — блок поименованных констант. Число — определяет константу, которой будет соответствовать первая запись (имя). Вторая запись будет соответствовать константе число+1, третья — константе число+2 и так далее. То есть, в нашем примере, везде, где компилятор увидит запись variable1, он вместо этой записи подставит число 20h (другая запись 0x20), вместо variable2 будет подставлено 21h и т.д.
С помощью этой директивы очень удобно присваивать имена сразу целому блоку пользовательских регистров (в которых программа будет хранить свои переменные или константы).
Пользовательские регистры контроллера PIC16F628A начинаются по адресу 20h. В нашем примере, поименовав константы, начиная со значения 20h, мы фактически назначили регистру по адресу 20h имя variable1, регистру по адресу 21h имя variable2 и т.д. Допустим, мы используем регистр по адресу 20h в качестве счётчика. Для того, чтобы увеличить значение счётчика нам нужно прибавить 1 к значению, записанному в этом регистре. На ассемблере это можно записать так: incf 20h. Но, у нас константе 20h соответствует имя variable1. То есть, мы можем записать incf variable1 и компилятор сам заменит variable1 на 20h. Согласитесь, вторая запись гораздо более наглядна.
То есть, с помощью директивы CBLOCK можно фактически определить блоки регистров (присвоить имена регистрам, расположенным по определённым адресам), которые будут использоваться в программе как переменные.
Блоков может быть несколько, главное внимательно следить, чтобы они не пересекались, а то получится, что две разных переменных расположены в одном и том же регистре. Конец блока обозначается директивой ENDC.
equ — эта директива сообщает компилятору, что запись, расположенная перед этой директивой соответствует числу, стоящему после этой директивы (компилятор будет заменять запись на число). В нашем примере, записи Const1 будет соответствовать число 1 (точка перед числом обозначает десятичную систему исчисления, а буква h — шестнадцатиричную), записи Const2 — число 5, записи TRISB — число 6 и т.д. С помощью этой директивы обычно задают константы, адреса используемых в программе регистров и присваивают имена отдельным битам в регистре.
Допустим в программе мы несколько раз в разных местах оперируем константой, значение которой равно 1 (например загружаем её в аккумулятор командой movlw .1). Если нам понадобится перекомпилировать программу с другим значением этой константы, то надо будет искать все куски кода, где мы её используем и в каждом случае отдельно менять код. Если же мы директивой equ указали, что записи Const1 соответствует константа 1, то теперь мы везде можем писать movlw Const1 и для изменения константы нам нужно всего лишь изменить её значение в шапке программы.
Аналогичным образом именуются используемые регистры. Например, мы хотим работать с портом B. Открываем документацию и смотрим, какие нам понадобятся регистры для работы с ним и по каким адресам они расположены. Мы видим, что для работы с портом B нам понадобится регистр, расположенный в нулевом банке по адресу 06h, который в доке называется PORTB и регистр, расположенный в первом банке по адресу 06h, который в доке называется TRISB. Пока компилятор не знает, что такое PORTB и TRISB, — мы можем обращаться к ним только по адресу. Например, если мы напишем movwf 06h, находясь в нулевом банке, то контроллер запишет данные из аккумулятора в регистр PORTB, а если та же команда будет выполнена, когда мы находимся в первом банке, то данные из аккумулятора будут записаны в регистр TRISB. Если мы в шапке программы пропишем, что имя PORTB соответствует числу 06h (PORTB equ 06h), то теперь в программе, для записи данных из аккумулятора в порт B, код может выглядеть так: movwf PORTB и компилятор будет знать, что запись PORTB нужно заменить на 06h. Точно так же можно поименовать и биты, указав, что, например, бит Z в регистре Status — это второй бит и везде, где мы пишем Z, компилятору нужно заменить эту запись на число 02h.
Короче говоря, шапка программы (за исключением слова конфигурации) нужна для облегчения последующего процесса программирования. То, что в ней записано, — это не код, который будет исполняться контроллером, а инструкции для компилятора, поясняющие как работать с написанным в теле программы кодом.
2. Тело программы.
В теле программы пишутся те инструкции, которые будут исполняться контроллером, то есть это как раз и есть сама программа для контроллера. Хотя, здесь тоже встречаются директивы, предназначенные для компилятора, например для правильного размещения участков программы в памяти контроллера.
ORG число — эта директива как раз предназначена для компилятора. Число в данном случае — это адрес, начиная с которого в памяти программ контроллера располагается код, следующий за директивой ORG. При старте, счётчик команд (указатель на текущую выполняемую команду) всегда устанавливается на нулевой адрес, поэтому логично, что мы должны разместить программу так, чтобы первая инструкция оказалась в памяти программ по нулевому адресу. Для этого в начале тела программы пишут ORG 0.
При возникновении прерывания счётчик так же всегда устанавливается по какому-то определённому адресу, например для PIC16F628A это будет адрес 0004h. Следовательно, если мы используем в программе прерывания, то перед подпрограммой обработки прерываний нужно написать ORG 04h, чтобы первая инструкция этой подпрограммы располагалась по адресу 0004h. Кроме того, в этом случае, необходимо обеспечить, чтобы основная программа не пересекалась с подпрограммой обработки прерывания.
Помните, мы указали, что программа должна располагаться в памяти программ, начиная с нулевого адреса. Соответственно, первая её инструкция будет по нулевому адресу, вторая по адресу 0001h, третья — по адресу 0002h, четвёртая по адресу 0003h, а пятая — по адресу 0004h. Опа! Начиная с пятой инструкции мы оказались в той области памяти, где должна располагаться подпрограмма обработки прерываний. Чтобы такого пересечения не произошло, подпрограмму обработки прерываний обходят командой goto. То есть, начиная с нулевого адреса до адреса 0002h можно разместить основную программу, а потом нужно сделать переход в ту область памяти, которая располагается за подпрограммой обработки прерывания и оставшуюся часть основной программы расположить там. В нашем примере (рисунок наверху) такой переход выполняется командой goto start.
Тело программы также можно поделить на 2 части — инициализацию и, собственно, выполнение какой-то задачи.
Инициализация — это настройка контроллера для решения нашей задачи. Поскольку контроллер — вещь многофункциональная и разные его части могут работать по разному, в зависимости от настроек (например, коэффициенты деления предделителя могут быть разные, ноги могут работать как входы или как выходы и т.д.), то сначала его нужно настроить для выполнения нашей конкретной задачи. Инициализация заключается в установке или сбросе определённых битов в соответствующих регистрах специального назначения. Как проводить инициализацию тех или иных частей контроллера (какие именно биты, в каких регистрах и в каком порядке нужно установить или сбросить) нужно читать в документации.
Пусть мы (для примера) хотим организовать мигание светодиодом, подключенным к 7-й ноге PIC16F628A. Для этого нам нужно, чтобы седьмая нога работала как выход. Седьмая нога — это канал RB0 порта B. Открываем доку и смотрим, что нужно сделать, чтобы настроить RB0 как выход. Мы видим, что направлением работы порта B управляет регистр TRISB, который находится по адресу 86h. 86h — это первый банк, смещение 06h от начала банка. Для того, чтобы RB0 работал как выход, нужно установить нулевой бит регистра TRISB в 0. То есть инициализация будет заключаться в следующем:
bcf PORTB, 0 ; устанавливаем начальное состояние ; (уровень, который установится на RB0 ; после переключения направления работы ; на выход, 0 - низкий уровень, 1 - высокий bsf Status, RP0 ; переходим в первый банк (нужный ; нам регистр TRISB находится там), для чего ; устанавливаем в 1 бит RP0 регистра Status bcf TRISB, 0 ; устанавливаем в 0 нулевой бит регистра TRISB ; (устанавливаем направление работы RB0 - на выход) bcf Status, RP0 ; возвращаемся в нулевой банк |
Только теперь (после инициализации), изменяя соответствующий бит в регистре PORTB, мы можем управлять уровнем сигнала на выводе RB0. (В данном примере показана настройка только одного из каналов порта, хотя на практике обычно настраивают порт целиком, соответственно используются команды, оперирующие с байтами, а не с битами).
На самом деле, несмотря на то, что инициализация находится в начале программы, процедуры инициализации, так же как регистры и переменные в шапке программы, прописываются в процессе разработки рабочей части программы. Мы ведь не можем заранее знать, какие нам понадобятся переменные, сколько, какими регистрами и модулями мы будем оперировать.
То есть, сначала нам надо разработать рабочую часть программы (которая и будет решать нашу конкретную задачу), а уже в процессе написания заполнять шапку и дописывать процедуры инициализации используемых модулей. Подробнее читайте об этом в следующей части.
- Часть 1. Необходимые инструменты и программы. Основы MPLAB
- Часть 2. Что такое микроконтроллер и как с ним работать
- Часть 3. Структура программы на ассемблере
- Часть 4. Разработка рабочей части программы. Алгоритмы
- Часть 5. Ассемблер. Организация циклов и ветвлений
- Часть 6. Как перевести контроллер в режим программирования и залить в него прошивку
ГЛАВА Сборка Введение 3.1
3,5 Введение Способность к общению велика
Процесс общения Физически « Программа » представляет собой Пример: ВОЗВРАТ 00 0000 0000 Подобно приведенному выше примеру, каждая инструкция ассемблера Ан 3.1 Представление чисел в В ассемблере MPLAB числа могут быть
Десятичные числа начинаются с точки, шестнадцатеричные 3.2 Язык ассемблера Основные элементы языка ассемблера
Этикетки Этикетка представляет собой текстовое обозначение (обычно
Инструкции Инструкции уже определены с использованием определенного
Операнды Операнды являются элементами инструкции для инструкции
Комментарии Комментарий — это набор слов, который программист Директивы Директива аналогична инструкции, но
3,3 Вт мощность В следующем примере показан простой При написании программы помимо обязательных правил Так как эти данные не важны для Чтобы нормально функционировать, мы должны _CONFIG Когда все Инструкции находятся в Следующим шагом является выбор банка памяти 0 и размещение 3.4 Директивы управления 3.1 Синтаксис: Описание: Пример: #define включено 1 Аналогичные директивы: #UNDEFINE, 3.2 Синтаксис: Описание: Пример: 3.3 Синтаксис: Описание: Пример: Аналогично 3.4 Синтаксис: Описание: Пример: Аналогичные директивы: SET, 3,5 Синтаксис: Описание: Пример: Аналогичные директивы: EQU, 3.6 Синтаксис: Описание: Пример: Аналогичные инструкции: SET 3,7 Синтаксис: Описание: Пример: Первые две инструкции, следующие за первой 3.8 КОНЕЦ Конец Синтаксис: Описание: Пример: 3,9 Синтаксис: Описание: Пример: Аналогичные директивы: #ELSE, 3.10 Синтаксис: Описание: Пример: Аналогичные инструкции: 3.11 Синтаксис: Описание: Пример: Аналогичные директивы: ELSE, 3. 12 Синтаксис: Описание: Пример: 3.13 Синтаксис: Описание: Пример: endw Аналогичные директивы: WHILE 3. 14 Синтаксис: Описание: Пример: Аналогичные директивы: 3.15 Синтаксис: Описание: Пример: Аналогичные директивы: #DEFINE, ELSE, 3.16 Синтаксис: Описание: Пример: cblock 0x02 Аналогичные директивы: 3.17 Синтаксис: Описание: Аналогичные директивы: 3.18 Синтаксис: Описание: Пример: Аналогичные инструкции: DE, DT 3.19 Синтаксис: Описание: Пример: Аналогичные инструкции: DB, DT 3.20 Синтаксис: Описание: Пример: Аналогичные директивы: DB, DE 3. 21 Синтаксис: Описание: Пример: Аналогичные директивы: _IDLOCS, 3.22 Синтаксис: Описание: Пример:
3.5 Файлы В результате процесса перевода
Первый файл содержит переведенную программу Пример файла «список» для программы в этом В конце файла «список» |
Язык ассемблера, часть 1 (микроконтроллер PIC)
Начиная с раздела 3, мы писали программы с веселой энергией. Для ясности эти списки были написаны в удобочитаемой форме. Таким образом, инструкции были представлены в виде короткой мнемоники, например, return вместо 00000000001000b; файловые регистры также имеют имена, такие как INTCON; строки были помечены и приложены комментарии. Такие символические изображения предназначены только для потребления человеком.
С помощью набора инструкций устройства, см. раздел A, можно выполнить перевод из удобочитаемой символьной формы в машиночитаемую двоичную. Это не особенно сложно для такого устройства, как PIC, которое имеет сокращенный набор инструкций (RISC) и несколько режимов адресации. Однако это медленно и утомительно, особенно когда кодируются программы значительной длины. Кроме того, он подвержен ошибкам и его трудно поддерживать всякий раз, когда необходимо внести изменения.
Компьютеры умеют делать скучные вещи быстро и точно; и перевод символического кода в машинный определенно попадает в эту категорию. Здесь мы кратко рассмотрим различные программные пакеты, помогающие в этом процессе перевода.
После прочтения этого раздела вы:
• Знать, что такое язык ассемблера и как он связан с машинным кодом.
• Оцените преимущества символьного представления по сравнению с машиночитаемым кодом.
• Понимание функций ассемблера.
• Поймите разницу между абсолютной и перемещаемой сборкой.
• Понимать роль компоновщика.
• Оцените процесс перевода и локализации программы на языке ассемблера в абсолютный машинный код.
• Понимать структуру файла машинного кода и роль программы-загрузчика.
• Понимание роли симулятора.
• Оцените использование интегрированной среды разработки для автоматизации взаимодействия различных программных инструментов, необходимых для преобразования исходного кода в запрограммированное устройство MCU.
Суть процесса преобразования представлена на рис. 8.1. Здесь программа готовится ручным человеком в символической форме, переваривается компьютером и выводится в машиночитаемой форме. Конечно, за этим простым утверждением скрывается гораздо более сложный процесс, и мы хотим изучить его достаточно подробно, чтобы помочь вам в написании ваших программ.
Рис. 8.1 Преобразование исходного кода на уровне сборки в машинный код.
Вообще разные переводчики и утилиты 9Компьютерные пакеты 0773 пишутся и продаются многими компаниями-разработчиками программного обеспечения, поэтому фактические детали и процедуры несколько различаются между различными коммерческими продуктами. В конкретном случае устройств PIC MCU компания Microchip Technology Inc. в соответствии со своей политикой всегда бесплатно предоставляла свои программные инструменты на уровне сборки, что является важным фактором их популярности. По этой причине коммерческое программное обеспечение PIC встречается относительно редко, и то, что есть, обычно соответствует синтаксису Microchip. По этой причине мы проиллюстрируем эту тему набором инструментов компьютерного кодирования Microchip.
Использование компьютера для помощи в переводе кода из более удобных для пользователя форм (известных как исходный код) в удобный для машин двоичный код (известный как объектный код или машинный код, и загрузка его в память началась в конце 1940-х годов для мэйнфреймов. По крайней мере, он позволял использовать системы счисления более высокого порядка, такие как шестнадцатеричная.1 В этой базе фрагмент кода на рис. в назначенных ячейках памяти.Этот загрузчик может быть частью программного обеспечения в вашем программаторе PIC-EPROM.Шестнадцатеричное кодирование мало что дает в его пользу, за исключением того, что число нажатий клавиш уменьшено, но клавиш больше, и их немного легче обнаружить некоторые типы ошибок
Для серьезного программирования требуется как минимум транслятор символов, или ассемблер2. Это позволяет программисту использовать мнемонику для инструкций и внутренних регистров с именами для констант, переменных и адресов. Символический язык, используемый в исходном коде, известен как язык ассемблера. В отличие от языков высокого уровня, таких как C или PASCAL, язык ассемблера имеет прямое отношение к сгенерированному машинному коду, т. е. одна строка исходного кода производит одну инструкцию. В качестве примера в программе 8.1 показана слегка измененная версия программы 6.11. Эта подпрограмма вычисляет квадратный корень из 16-битной переменной с именем NUM, которой было выделено два байта в хранилище данных.
Давать имена адресам и константам особенно полезно для более длинных программ, которые легко могут превышать 1000 строк. Вместе с использованием комментариев это упрощает отладку, разработку и сопровождение кода. Таким образом, если мы хотим изменить файловые регистры, содержащие переменную NUM, с Файла 20:21 h на, скажем, Файл 36:37h, нам нужно всего лишь изменить строку:
cblock 20h
на:
. cblock 36h
, а затем ретранслировать в машинный код. В программе с, скажем, 50 ссылками на переменную NUM альтернатива изменения всех этих адресов вручную с 20h или 21h (старший: младший байт) на 36h или 37h соответственно трудоемка и подвержена ошибкам. В теле нашего исходного кода старший байт обозначается как NUM (это содержимое файла 20h), а младший байт в файле 21h — как NUM+1, поскольку ассемблеры могут выполнять простые арифметические операции с символическими константами.
Псевдоинструкция cblock является примером директивы ассемблера. Директива — это команда программиста ассемблеру, касающаяся его работы или присвоения имени константе. Мы перечисляем небольшое подмножество директив ассемблера Microchip в конце темы, читатель должен обратиться к официальному руководству для подробного описания. Вкратце директивы, используемые в программе 8.1, таковы: cblock – endc
Скорее похоже на блок директив equ , дающий инкапсулированный список констант меток, начинающихся либо с указанного значения, например. 20h или после последнего блока c, если адрес не указан. Можно считать, что помеченные объекты занимают более одного байта, если использовать поле размера, разделенное двоеточием; например, NUM:2 для 2-байтового выделения и обычно используются для обозначения регистров общего назначения (GPR).
Программа 8.1 Абсолютный код уровня ассемблера для нашего модуля извлечения квадратного корня.
end
Сообщает ассемблеру, что это конец исходного кода. equ
Связывает значение с символом. Например, ассемблер заменяет имя STATUS на значение 3 везде, где оно появляется в операнде инструкции. Обычно используется для регистров специального назначения (SPR) и битов в файловых регистрах.
org
Указывает начальный адрес для следующего кода, в противном случае ассемблер по умолчанию использует 000h в хранилище программ. В этой программе подпрограмма SQR_ROOT запускается в 200 часов.
Конечно, символьные трансляторы требуют большей вычислительной мощности, чем простые шестнадцатеричные загрузчики, особенно в области памяти и хранилища резервных копий. До появления персональных компьютеров в конце 1970-х годов для реализации процесса сборки требовались либо мейнфреймы, миникомпьютеры, либо специальные системы разработки MPU/MCU. Такие реализации неизбежно были дорогими и препятствовали использованию таких компьютерных средств, а ручное кодирование было относительно обычным явлением. Таким образом, программное обеспечение для перевода выполняет две задачи:
• Преобразование различных мнемоник и меток инструкций в их эквиваленты в машинном коде. тема
• Расположение инструкций и данных в соответствующей ячейке памяти.
Второй из них, пожалуй, труднее понять.
Программа 8.2 предназначена для обработки абсолютным ассемблером. Здесь программист использует директиву org, чтобы указать ассемблеру поместить код в указанный адрес хранилища программ. Это означает, что программист должен знать, где что размещать. Этот процесс абсолютной сборки показан на рис. 8.2. Абсолютная сборка подходит там, где в реальных проектах программа содержится в одном автономном файле; что характерно для большей части кода в этом тексте. часто состоят из нескольких тысяч строк кода и требуют командной работы. Поскольку многие модули написаны разными людьми, возможно, также из внешних источников и библиотек, необходимо найти какие-то средства для связывания соответствующих модулей вместе, чтобы получить один исполняемый файл с машинным кодом. Например, вам может понадобиться вызвать подпрограмму деления, которую Фред написал некоторое время назад. Вы не будете точно знать, где в памяти будет находиться эта подпрограмма, пока проект не будет завершен. Что ты можешь сделать? Итак, точка входа подпрограммы должна быть помечена; скажем, DIV в этом случае. Вы должны иметь возможность указать ассемблеру присвоить этой метке атрибут, что ее абсолютное значение должно быть найдено позже программой компоновщика. Мы рассмотрим этот перемещаемый способ работы позже в этой теме.
Большинство программ, работающих на PIC низкого и среднего уровня, адекватно обрабатываются абсолютным ассемблером. Чтобы прояснить процесс, мы проведем подпрограмму на рис. 8.2 от создания исходного файла до конечного файла с абсолютным машинным кодом.
Редактирование
Первоначально исходный файл должен быть создан с помощью текстового редактора. Текстовый редактор отличается от текстового процессора тем, что в него не вставляются встроенные управляющие коды, задающие форматирование и другую информацию.
Рис. 8.2 Абсолютная трансляция кода на уровне ассемблера.
Например, нет переноса строк; если вы хотите новую строку, нажмите клавишу [ENT]. Большинство операционных систем поставляются с простым текстовым редактором; например блокнот для Microsoft Windows. Также доступны сторонние продукты, и большинство текстовых процессоров имеют текстовый режим, который можно использовать как редактор программ.3 Имена исходных файлов на уровне сборки, совместимые с Microchip, имеют расширение .src.
Формат типичной строки исходного кода выглядит следующим образом:
За исключением строк только для комментариев, все строки должны содержать инструкцию (либо исполняемую MCU, либо директиву) и любую соответствующую операнд или операнды. Любая метка должна начинаться в столбце 1, в противном случае первым символом должен быть пробел или табуляция, чтобы указать отсутствие метки. Метка может содержать до 32 буквенно-цифровых символов, символов подчеркивания или вопросительного знака при условии, что первым символом является подчеркивание или буква. Метки обычно чувствительны к регистру. Метка строки указывает адрес хранилища программ первой следующей исполняемой инструкции.
Необязательный комментарий выделяется точкой с запятой , разрешены комментарии целиком – см. строки 11-18 программы 8.1. Комментарии игнорируются ассемблером и предназначены исключительно для удобочитаемой документации. Примечания должны быть обильными и должны объяснять, что делает программа, а не просто повторять инструкцию. Например:
— это пустая трата энергии:
гораздо полезнее. Отсутствие или минимальное комментирование исходного кода является частым недостатком, и не ограничивается только студентами.
Добавить комментарий