Вы находитесь на странице: 1из 22

Введение в язык

Ассемблера
Лекция 2

Проф. О.В. Непомнящий


1
План лекции
1. Основные термины
2. Что такое ассемблер?
3. Ассемблер для микроконтроллера. Как устроена программа.
4. Инструкции, метки и директивы
5. Функции
6. Примеры программ
7. Задания
8. STK500
9. Литература для чтения и видео для просмотра

2
Терминология
1. Язык ассемблера - это любой язык программирования низкого
уровня, в котором существует очень строгое соответствие между
инструкциями на языке и инструкциями машинного кода для
конкретной архитектуры процессора.
2. Инструкции - это специальные мнемоники, которые ассемблер
переводит в машинный код. Как следует из названия, они
«приказывают» процессору что-то делать.
3. Директивы - это руководства для транслятора, используемые им для
автоматизации процесса сборки и улучшения читаемости
программы.
4. Функция - это блок организованного многократно используемого
кода, который используется для выполнения одного связанного
действия.

3
Что такое ассемблер?
Ассемблер - это язык низкого уровня.
В чем его отличие от языков высокого уровня?
В языках высокого уровня программы не зависят от
оборудования или возможностей процессора. Эти
программы работают на разных процессорах, если
существует компилятор для этого языка и семейства
процессоров. Компилятор переводит эти языковые
конструкции на двоичный язык процессора.
4
Ассемблер для микроконтроллера
Идея ассемблера - сделать доступными Memory
аппаратные ресурсы процессора.
Под ресурсами будем понимать все
аппаратные компоненты, например
центральный процессор (ЦП) и его
математический сопроцессор, арифметико-
логический блок (АЛУ), различные блоки
хранения (внутренняя и внешняя RAM,
память EEPROM),порты, регистры
управления и настройки портов, таймеров,
аналого-цифровых преобразователей и assembler C
других устройств.
5
Ассемблер для микроконтроллера
Доступный ресурс - означает прямой доступ, а не через
драйверы или другие интерфейсы, которые предоставляет
операционная система. Это означает, что вы управляете
последовательным интерфейсом или аналого-цифровым
преобразователем и между оборудованием и вашей
программой нет никаких других драйверов, никакого
промежуточного слоя. Награда за ваши усилия - все
оборудование находится в вашем распоряжении, а не
только часть, которую вам предоставляют разработчик
компилятора и программист операционной системы.

6
Зачем учить ассемблер?
• Изучение ассемблера позволяет вам полностью оптимизировать
код для любой ситуации и позволяет писать программы, которые
делают именно то, что вы хотите, так, как вы хотите, чтобы
компилятор не пытался периначить вашу программу.
• Изучение ассемблера дает вам полную прозрачность в вашей
программе и, что самое главное, сделает вас лучшим
программистом на C.
• Кроме того, критичные ко времени алгоритмы могут быть написаны
на ассемблере и вызваны из основной программы, написанной на
C. Смешивание этих двух языков позволяет вам использовать
сильные стороны каждого языка для создания наилучших
программ.
7
Как устроена программа?
Программы на ассемблере будут сильно отличаться от программ на языке C,
к которым вы привыкли. В коде программы строки организованы в столбцы
для удобства чтения и обычно содержат метки, директивы или инструкции,
за которыми следуют один или два операнда. Кстати операндов может и не
быть.
Каждый из этих элементов может быть помещен в любой столбец по выбору
программиста, хотя порядок, в котором они расположены, имеет значение.
Обычно первый столбец оставляют для меток, а инструкции размещают во
втором или третьем.
.cseg ; директива
lbl1: .byte 10 ; метка перед директивой с аргументов
lbl2: add r22,r23 ; метка перед инструкцией с двумя операндами
inc r22 ; инструкция с одним операндом
nop ; инструкция без операндов
8
Инструкции
Инструкции могут содержать один, два или ни одного
операнда, которые должны сразу следовать за ним в
одной строке. Обратите внимание, что указанные
выше операнды должны быть разделены запятой.
Кроме того, они помещены в следующий столбец для
облегчения чтения.

add r16,r17 ; сложить r16 and r17


dec r16 ; уменьшить r16
9
Метки
Метки – это адреса памяти программ в которых
расположены инструкции, поэтому они не
транслируются в загрузочный двоичный код, но
используются программистом для присвоения here: jmp here
определенному участку кода имени. Во время
компиляции метка будет преобразована в адрес
программы, который может использоваться как here:
цель для инструкций безусловного или jmp here
условного перехода.
В программе метки отделяются двоеточием, но
при использовании ее качестве операнда метка
указывается без двоеточия.
10
Директивы (.Include)
Распространенной директивой является .include,
которая копирует содержимое файла в код.
.include "m328pdef.inc“ .include "m328Pdef.inc“
.org 0x0000
jmp Reset
.org 0x0020
jmp Tim0Ovf
.org 0x0036

11
Директивы (.def)
Директива .def позволяет привязать к любому слову любое значение из
ресурсов контроллера — порт или регистр. Например сделал я счетчик, а
считаемое значение находится в регистре R0, а в качестве регистра-
помойки для промежуточных данных я заюзал R16. Чтобы не запутаться и
помнить, что в каком регистре у меня задумано я присваиваю им через
.def символические имена.
.def schetchik = R0
.def pomoika = R16
ADD schetchik, pomoika
И теперь в коде могу смело использовать вместо официального имени R0
неофицальную кличку schetchik. Одному и тому же регистру можно давать
кучу имен одновременно и на все он будет честно откликаться.
Директивы (.EQU)
Директива .equ это присвоение выражения или константы какой либо
символической метке.
Например, у меня есть константа которая часто используется. Можно, конечно,
каждый раз писать ее в коде, но вдруг окажется, что константа выбрана неверно, а
значит придется весь код шерстить и везде править, а если где-нибудь забудешь, то
получишь такую махровую багу, что задолбаешься потом ее вылавливать. Так что
нафиг, все константы писать надо через .equ!
Кроме того, можно же присвоить не константу, а целое выражение. Которое при
компиляции посчитается препроцессором, а в код пойдет уже исходное значение.
Надо только учитывать, что деление тут исключительно целочисленное. С
отбрасыванием дробной части, без какого-либо округления, а значит 1/2 = 0, а 5/2 = 2
.equ Time = 5
.equ Acсelerate = 4
.equ Half_Speed = (Accelerate*Time)/2
Директивы (.CSEG)
.CSEG сегмент кода, он же флеш. После этой директивы идет тело программы,
команды процессора. Тут же можно засунуть какие ни будь данные которые не
меняются, например таблицу с заранее посчитанными значениями, статичный текст
или таблицу символов для знакогенератора. Делается это при помощи директив:
.db массив байтов. .dw массив слов —два байта.
.dd массив двойных слов — четыре байта .dq массив четверных слов — восемь байт.
Например так:
.CSEG
Constant: .db 10 ; или 0хAh в шестнадцатеричном коде
Message: .db "Привет лунатикам"
Words: .dw 10, 11, 12
В итоге, во флеше вначале будет лежать число 0А, затем побайтно будут хекскоды
символов фразы «привет лунатикам», а дальше 000A, 000B, 000С.
Последние числа, хоть сами и невелики, но занимают по два байта каждое, так как
объявлены как .dw.
Директивы (.org, .dseg)
.ORG address означает примерно следующее «копать отсюда и до обеда», т.е. до
конца памяти. Данный оператор указывает с какого адреса пойдет то что после этой
диррективы. Обычно используется для создания таблицы прерываний. Еще может
применятся в сегменте данных (см. далее) для резервирования данных по
конкретному адресу.
.DSEG сегмент данных, оперативка. Те самые жалкие считанные байты. Сюда не
зазорно пихать переменные, делать тут буфера, тут же находится стек.
Тут действует дирректива .BYTE позволяющая указать на расположение данных в
памяти.
Например так:
var1: .BYTE 1
table: .BYTE 10
В первом случае мы указали переменную var1 состоящую из одного байта.
Во втором случае у нас есть цепочка из 10 байт и метка (адрес) table указывающая на
первый байт из цепочки. Адрес остальных вычисляется смещением.
Директивы (.db, .dw)
.DB и.DW - это директивы, позволяющие поместить во флэш-память список констант или строку
текста и прочитать их.

.DB 123,45,67,89 ; список из четырех байтов, в десятичной системе счисления


.DB “This is a text. “ ; список байтовых символов, записанный как текст
.DW 12345,6789 ; список констант из двух слов

.byte директива резервирует один или несколько последовательных байтов в текущем разделе
памяти данных.

.byte 10 ; зарезервировать 10 байт в памяти

Если вы используете метку, она указывает на расположение первого инициализируемого байта.


mas: .byte 10 ; зарезервировать 10 байт в памяти начиная с адреса с именем mas

16
Комментарии
Комментарии в программе начинаются с точки с запятой.
Комментарии обычно помещаются в крайний правый столбец
строки кода.

add r16,r17 ; add the contents of register 16 and 17

Если вы используете MicrochipStudio, вы также можете


использовать // и / * * / для обозначения комментариев, хотя это
не поддерживается некоторыми другими ассемблерами.
17
Ассемблер Atmel AVR
; Команды (инструкции) ;Числа ;Функции
add r26,r27
inc r23 250 – десятичное LOW ()
andi r23,0b01110111 045 – Восьмеричное HIGH ()
rjmp metka $1F – Шестнадцатеричное BYTE2 (), BYTE3 (), BYTE4 ()
brsh metka2
mov r22,r21 0x1F – Шестнадцатеричное EXP2 ()
ldi r23,$5F 0b11001100 - Двоичное
st z+,r23 ;Операции
;Директивы транслятора
ld r31,x .BYTE .DB .DW
! Отрицание
lsl r21 +- Плюс, Минус
ror r22 .CSEG .DSEG .ESEG
nop << >> Cдвиг в лево/право
.EQU
in r23,DDRA .INCLUDE
< > Меньше/Больше
out PIND,r30 == Равно
Lpm .ORG
Clz != Не равно
.SET
rcall Pprogam & Побитовое «И»
ret | Побитовое «ИЛИ»
https://dfe.karelia.ru/koi/posob/avrlab/avrasm-rus.htm - Cправка на русском
Встроенные в ассемблер функции
(low, high)
Функция low() возвращает 8 младших бит аргумента.
Функция high() возвращает 8 старших аргумента

Array: .db 10, 0x12 ; Начиная с адреса Array определить


; в памяти два числа 10 и
; 0х12(шестьнадцатеричное)

ldi r30, low (Array)


ldi r31, high (Array)

19
Как это работает?
Example Data segment Command segment
.dseg RAM FLASH
.org 0x70 Address Address
Array:. byte 6 $0060 ? $0000 ldi r30, low (Array)
.cseg … … ldi r31, high (Array)
ldi r30, low (Array) $0070 byte0 ld r28, Z+
ldi r31, high (Array) $0071 byte1
ld r28,Z+ … ... Z - register
The result of r28 is 10, $0075 byte5 $00 $70
Z=r31:r30=0x71 …
? $00 $71
Z – register ++
20
Потренируемся
1. ldi r22, 10 084 <255 6. add r21, r22, r23
adi
2. add r22, 5 7. add r23, r34 <r32

3. dec x , 1 8. .dseg
.byte 10
" "
4. .include ‘m8def.inc’ .db 1,3,-5
=
5. .def temp, R16
21
Лабораторный стенд STK500
Разъемы Панели Выходы
Кнопка «сброс»
портов для ЧИПа микроконтроллера
Кнопки
Кнопка питания
Разъем для programming
кнопок port Разъем питания

Разъем RS-232 Порт для внешнего


программирования
Пользовательский
Разъем
интерфейс
DataFlash
Кнопка внутреннего
Разъем для программирования
светодиодов Светодиоды Выходы Разъемы для подключения
микроконтроллера кабеля программатора 22

Вам также может понравиться