Перший цикл Fetch → Decode → Execute
Чому світлодіод ще не блимає
У попередньому розділі ми з’ясували, що процесор нічого не знає про світлодіоди, кнопки чи дисплеї. Тепер виникає інше питання. Як він взагалі виконує програму? Відкрийте будь-який файл на C.
int a = 5;
int b = 8;
int c = a + b;
Людина миттєво розуміє зміст цього коду. Процесор — ні. Для нього це лише послідовність машинних інструкцій.
Наприклад:
LDR
LDR
ADD
STR
або навіть
111010101001001001...
Для ARM Cortex-M будь-яка програма — це лише довгий потік чисел.
І тепер головне питання:
Як процесор знає, яку інструкцію потрібно виконати саме зараз?
Лічильник команд
Всередині будь-якого процесора існує спеціальний регістр. В ARM він називається
Program Counter
PC
Це один із найважливіших регістрів процесора. Він містить лише одну інформацію — адресу наступної інструкції.
Наприклад. Flash пам’ять містить
| Адреса | Інструкція |
|---|---|
| 0x08000000 | MOV |
| 0x08000002 | ADD |
| 0x08000004 | STR |
| 0x08000006 | B |
Припустимо
PC = 0x08000000
Процесор дивиться саме сюди. Не вперед. Не назад. Саме сюди.
Крок 1. Fetch
Перший етап називається Fetch тобто “отримати інструкцію”.
Процесор звертається до Flash.
Flash
↓
0x08000000
↓
MOV R0,#5
Після цього інструкція потрапляє всередину ядра. Поки що вона ще не виконується. Вона лише прочитана.
Крок 2. Decode
Тепер процесор повинен зрозуміти, що означає набір бітів.
Наприклад
0010000010101010
Для нас це безглуздий набір цифр. Для декодера ARM це означає
MOV R0,#5
Саме тому цей етап називається Decode тобто “розшифрувати інструкцію”.
Крок 3. Execute
Тепер процесор виконує інструкцію.
MOV R0,#5
означає
R0 = 5
Після цього процесор автоматично змінює
PC
на адресу наступної інструкції. Наприклад було
0x08000000
стало
0x08000002
І цикл починається знову.
Один цикл життя процесора
Усе життя процесора можна намалювати однією схемою.
Program Counter
↓
Fetch
↓
Decode
↓
Execute
↓
Program Counter++
↓
Fetch
↓
Decode
↓
Execute
Він повторюється мільйони, мільярди, трильйони разів.
А якщо потрібно перейти в інше місце?
Припустимо
if(a==5)
{
...
}
або
while(1)
{
}
Тоді процесор не додає адресу автоматично. Виконується спеціальна інструкція
B
або
BL
яка просто записує в
PC
нову адресу. Саме тому цикл, умови, функції, переривання — усе це насправді лише зміна одного регістра.
Цікавий факт
Коли ви пишете
while(1)
{
}
ви думаєте, що процесор “ходить по циклу”. Насправді відбувається ось що.
PC
↓
B
↓
PC
↓
B
↓
PC
↓
B
↓
...
Він постійно переписує адресу самого себе.
Інтерактивна лабораторія
Тепер відкрийте лабораторію
Спробуйте:
- запускати процесор по одному такту;
- змінювати PC вручну;
- спостерігати Fetch;
- дивитися Decode;
- бачити Execute;
- виконати кілька інструкцій;
- зробити перехід;
- виконати нескінченний цикл.
Не намагайтеся запам’ятати всі команди. Ваше завдання — побачити, що процесор живе одним нескінченним циклом.
Практика
Уявіть програму
int x=0;
x++;
x++;
x++;
Не запускаючи компілятор,
спробуйте відповісти.
- Скільки інструкцій приблизно виконає процесор?
- Скільки разів зміниться Program Counter?
- Чи існує хоч один момент, коли процесор нічого не робить?
Контрольні питання
- Для чого потрібен Program Counter?
- Що відбувається під час Fetch?
- Що робить Decode?
- Коли інструкція реально змінює стан процесора?
- Чому цикл
while(1)ніколи не завершується? - Як процесор переходить до іншої функції?
Підсумок
Тепер ви знаєте головний секрет будь-якого процесора.
Він не виконує “програму” так, як це уявляє людина. Для нього існує лише нескінченний цикл: прочитати інструкцію, зрозуміти її, виконати та перейти до наступної.
Усі складні конструкції мов програмування — цикли, умови, виклики функцій — зрештою зводяться до зміни регістра Program Counter.
Це розуміння стане основою для наступного розділу, адже ми вже знаємо, як процесор виконує інструкції. Настав час розібратися, де він тимчасово зберігає дані під час їх виконання.
Далі
У наступному розділі ми познайомимося з регістрами ARM Cortex-M. Ви дізнаєтеся, чому вони є найшвидшою пам’яттю в системі, навіщо потрібні R0–R12, SP, LR і PC, і чому саме через них проходить практично кожна інструкція, яку виконує процесор.