Слайд 2
Краткое содержание предыдущей серии
Что такое CISC и RISC?
В
чем их основные отличия?
Что это такое и что здесь
что?
0x08000330 6011 STR r1,[r2,#0x00]
Что такое адресация?
Какие способы адресации вы помните?
Слайд 3
Краткое содержание этой серии
Типизация в языках программирования
Команды загрузки
и сохранения
Подробнее о длинных и коротких командах Thumb-2
Чудеса языка
С
О стиле написания кода
Слайд 4
Типизация в языках программирования
О чем речь?
Типизация –
способ задания типа объекта.
А что такое тип?
Простым языком тип
– это смысл, который несет объект.
Тип ограничивает область допустимых значений и допустимых действий над объектом.
Более формально см. «теория типов»
Слайд 5
Виды типизации
По наличию типизации языки программирования бывают:
Типизированные (C,
C++, Java, Python...) – работа с «объектами»
Бестиповые (Ассемблер, Brainfuck..)
– работа с памятью напрямую
Типизация бывает:
Статическая и динамическая.
Сильная (строгая) и слабая (нестрогая).
Явная и неявная (и утиная).
Все это разные свойства. Т.е. типизация в одном языке может быть статическая, строгая и явная, например.
Подробнее http://habrahabr.ru/post/161205/
Слайд 6
По времени определения типа
Но в языках со статической
типизацией можно руками сделать динамическую.
Иногда, можно и наоборот.
Слайд 7
По силе (строгости)
Обычно автоматически приводятся не любые типы
к любым типам. Например, приведение числа к массиву весьма
неоднозначно (см. “javascript wat”)
В строго-типизированных языках иногда разрешается «расширение» (promotion) – например, short автоматически приводится к int.
Слайд 8
По «явности»
В языке с явной типизацией бывает «неявная
типизация по выбору»
И наоборот тоже бывает.
Утиный тест: если что-то
выглядит, как утка, крякает как утка и летает, как утка – это утка
Слайд 9
Бестиповой ассемблер – это как?
Никаких переменных нет, есть
только память
Но на память можно «смотреть» по-разному (как на
int или как на char)
В RISC «смотреть» в память можно только командами загрузки и сохранения
Слайд 10
Memory Map в STM32
Процессор 32-битный, адресное пространство тоже
32-битное.
Значит, адреса в памяти меняются от 0 до
232-1
И максимальный адресуемый диапазон памяти – 4 Гб.
Но в контроллере всего лишь 128 Кб Flash-памяти и 20 Кб ОЗУ.
Слайд 11
Memory Map в STM32 (упрощенная)
Код выполняется прямо из
Flash-памяти
Переменные хранятся в ОЗУ
Слайд 12
Команды загрузки и сохранения
Команда загрузки – load –
LDR – загружает значение из памяти в регистр
LDR r0,[pc,#28]
Команда
сохранения – store – STR – сохраняет значение из регистра в память
STR r1,[r0,#0x0C]
Слайд 13
И команды работы со стеком
PUSH – поместить значение
регистров в стек
PUSH {r4-r6,lr}
POP – вынуть значения из стека
и положить в регистры
POP {r4,pc}
Стек находится в той же оперативной памяти.
Эти команды эквивалентны STM и LDM от Stack Pointer’a
Слайд 14
Где «тип» же в командах?
«Как мы смотрим» на
память задается с помощью постфиксов:
LDR – загрузить слово (word,
4 байта)
LDRH – загрузить полуслово (halfword, 2 байта)
LDRB – загрузить байт (byte)
LDRSB – загрузить знаковый байт (signed byte)
LDRSH – загрузить знаковое полуслово (signed halfword)
LDRD – загрузить двойное слово (double word, 8 байт)
LDRM – загрузить много байт (multiple)
Для STR аналогично.
Есть еще постфиксы, которые к типу не относятся.
У POP и PUSH «типовых» постфиксов нет.
Слайд 15
Типы С и ассемблер
Между целочисленными типами и командами
соотношение очевидное
А как же float и double?
float – 4
байта, специализированных регистров для него нет – поэтому просто LDR
double – 8 байт – просто LDRD
Слайд 16
Длинные и короткие команды
Как процессор узнает, длинную команду
нужно выполнить или короткую?
Раньше (в ARMv5) было просто два
режима
В ARMv7 хитрее – в коде команды написано, длинная она или нет
Слайд 17
Длинные и короткие команды
Процессор считывает 16 бит по
адресу, указанному в РС.
Если биты с 15 по
11 это:
11101 или
11110 или
11111 – то команда длинная. И нужно считать еще 16 бит.
Иначе: команда короткая
Поэтому коды длинных команд часто начинаются на F
Слайд 18
Структура короткой команды на примере MOVS r0,#0x05
0x2005 =
0010 0000 0000 0101
Пять старших бит (opcode) показывают что
это, собственно, команда mov
Биты 10, 9 и 8 задают номер регистра
Биты с 7 по 0 задают непосредственный операнд
Это кодирование Т2
Слайд 19
Структура длинной команды (ADDW)
ADDW Rn, Rd, Imm ->
Rd = Rn + Imm12
Зеленое – opcode (в частности
показывает, что команда длинная)
Rn – регистр-слагаемое
Rd – регистр-приемник результата
Imm12 – число, собираемое из i:imm3:imm8 – 12 бит
Это кодирование T4
Слайд 20
Пример ADDW
F600401A ADDW r0,r0,#0xC1A
C1A = 1100
0001 1010
F600401A =
Слайд 21
Структура длинной команды (ADD)
ADD Rn, Rd, Imm ->
Rd = Rn + Imm32
Зеленое – opcode (в частности
показывает, что команда длинная)
Rn – регистр-слагаемое
Rd – регистр-приемник результата
S – опциональный бит (обновлять ли флаги состояния)
Imm32 – число, задаваемое i:imm3:imm8 – хитрым образом!
Это кодирование T3
Слайд 22
Непосредственный операнд при кодировании Т3
Часть первая:
Слайд 23
Непосредственный операнд при кодировании Т3
Часть вторая:
Слайд 24
Непосредственный операнд при кодировании Т3
Часть вторая:
Слайд 25
Пример команды ADD c кодированием Т3
F5001090 ADD
r0,r0,#0x120000
0x12 = 10010
0x12
0000 = 1001 (и 17 нулей)
Т.е. позиция значащего бита – 17? Не факт. Закодировать это число можно по-разному
i = 1, imm3 = 1, a = 1 значит позиция младшего бита = 32 -100112 = 13
Значит, imm32 = 1001 0000 << 13.
Проверяем.
F5001090 =
Слайд 26
«Святые писания»
Cortex-M3 Devices Generic User Guide:
Программная модель ядра
процессора
Описание синтаксиса и семантики инструкций процессора
Периферия уровня ядра
ARMv7-M Architecture
Reference Manual:
Подробное описание ядра процессора
Кодирование инструкций
STM32F10x Reference Manual:
Подробное описание всех периферийных устройств семейства микроконтроллеров
STM32F103x8 Datasheet:
Электрические характеристики конкретной модели МК
Распиновка, габариты и т.д.
Слайд 27
«Святые писания»
Errata sheet:
Описание всех известных производителю ошибок в
конкретном МК или серии МК
Спецификация микроконтроллеров Миландр серии 1986ВЕ9х:
Единственный
документ о МК Миландр
Страницы 51-141 являются плохим переводом трех глав Cortex-M3 User Guide!
Слайд 29
Краткий экскурс в историю
Язык С появился в ~1973
году.
Компьютеры были очень разные.
С – «кроссплатформенный ассемблер».
Поэтому очень
много вещей в С зависят от платформы, для которой программа написана.
Очень много вещей – это наследство от старых времен
Слайд 30
Типы в языке С
Типизация: статическая слабая и неявная.
«Простые»
типы:
_Bool (bool) – начиная с С99 - #include
char, signed char, unsigned char
short
int
long
long long
float, double, long double
void
указатели
Композитные: массивы, структуры, объединения
Функции
Выражения
Слайд 31
Как искать чудеса?
Читать Стандарт языка (С89, С99, С03)
Искать
на stackoverflow.com
Просто писать программы! Чудо рано или поздно найдет
вас.
Слайд 32
Чудо первое: размеры типов
Оператор sizeof возвращает размеры в
размерах типа char
Количество бит в одном char задается в
макросе CHAR_BITS
Для всех остальных типов задаются минимальные диапазоны
Слайд 33
Чудо первое: размеры типов
Как жить с этим чудом?
Использовать типы с известной длиной!
#include
char – чтобы хранить
символы (а не числа)
int8_t – знаковый 8 бит
uint8_t – беззнаковый 8
int16_t – знаковый 16 бит
uint16_t – беззнаковый 16 бит и т.д. вплоть до 64
Тип
char
short
int
long
long long
Размер в битах
не менее 8
не менее 16
не менее 16
не менее 32
не менее 64
Слайд 35
Чудо второе: поведение
Компиляторы не всегда предупреждают
Компиляторы не всегда
следуют стандарту
Как жить с этим чудом?
Не выключать предупреждения
(warning)
ЧИТАТЬ предупреждения! Ценить, что они вообще есть.
Помнить, что отсутствие предупреждений не означает, что все хорошо.
Слайд 36
Чудо третье, неожиданное
Если поведение определенное, это еще не
значит, что оно очевидное.
Примеры:
Правила неявного преобразования типов
Приоритеты операторов
Арифметика с
плавающей точкой (не только в С!)
Макросы
Указатели, указатели, указатели..
Компиляция с оптимизацией усиливают чудеса!
Слайд 37
Чудо третье, неожиданное
Как жить с чудесами?
Учиться, учиться и
еще раз учиться.
Или искать другой язык.
Но в каждом языке
есть свои чудеса!
Слайд 38
Немножко о стиле кода
Пишите комментарии о смысле происходящего
Если
у вас больше трех переменных – называйте их осмысленно.
Ставьте
отступы!