Ви взагалі не можете цього зробити, але в деяких сенсах ви дуже можете, і було декілька історичних випадків, коли вам справді довелося .
Atari 2600 (або Atari Відеосистема комп'ютера) був один з найбільш ранніх домашнього відео ігрових систем і вперше була випущена в 1978 р В відміну від більш пізніх систем епохи, Atari не може дозволити собі , щоб дати пристрою буфер кадру, а це означає , що процесор мав запускати код на кожній лінії сканування, щоб визначити, що потрібно створити - якби цей код запустив 17,08 мікросекунд (інтервал HBlank), графіка не була б встановлена належним чином, перш ніж лінійка сканування почала їх малювати. Гірше, якщо програміст хотів намалювати складніший вміст, ніж те, що зазвичай дозволяють Atari, вони повинні були виміряти точний час для вказівок та змінити графічні регістри під час малювання променя з проміжком 57,29 мікросекунд для всієї лінії сканування.
Однак Atari 2600, як і багато інших систем на базі 6502, мав дуже важливу особливість, яка дозволяла ретельно керувати часом, необхідним для цього сценарію: процесор, оперативна пам’ять та телевізійний сигнал усі вичерпували годинники на базі одного і того ж майстра годинник. Сигнал телевізора пробігав тактовою частотою 3,98 МГц, розподіляючи вищевикладене число на цілу кількість "кольорових годин", які керували телевізійним сигналом, а цикл тактових процесорів та оперативної пам’яті складав рівно три кольорових тактових годин, дозволяючи годиннику процесора бути точний показник часу відносно поточного телевізійного сигналу прогресу. (Для отримання додаткової інформації про це перегляньте посібник програміста Stella , написаний для емулятора Stella Atari 2600 ).
Крім того, це середовище роботи означало, що кожна інструкція процесора мала певну кількість циклів, яку вона потребує у кожному випадку, і багато 6502 розробників публікували цю інформацію у довідкових таблицях. Наприклад, розгляньте цей запис для інструкції CMP
(Порівняйте пам'ять з акумулятором), взятої з цієї таблиці :
CMP Compare Memory with Accumulator
A - M N Z C I D V
+ + + - - -
addressing assembler opc bytes cycles
--------------------------------------------
immediate CMP #oper C9 2 2
zeropage CMP oper C5 2 3
zeropage,X CMP oper,X D5 2 4
absolute CMP oper CD 3 4
absolute,X CMP oper,X DD 3 4*
absolute,Y CMP oper,Y D9 3 4*
(indirect,X) CMP (oper,X) C1 2 6
(indirect),Y CMP (oper),Y D1 2 5*
* add 1 to cycles if page boundary is crossed
Користуючись усією цією інформацією, Atari 2600 (та інші 6502 розробники) змогли точно визначити, як довго триває їх код для виконання, і побудувати підпрограми, які виконували те, що потрібно, і досі відповідали вимогам Atari щодо телевізійних сигналів. І оскільки цей термін був настільки точним (особливо для інструкцій, що витрачають час, як NOP), вони навіть змогли використовувати його для зміни графіки під час їх малювання.
Звичайно, 650 Atari - це дуже специфічний випадок, і все це можливо лише тому, що система мала все наступне:
- Головний годинник, який керував усім, включаючи оперативну пам’ять. Сучасні системи мають незалежні тактові частоти для процесора та оперативної пам’яті, при цьому частота оперативної пам’яті часто буває повільнішою, а дві не обов'язково синхронізовані.
- Жодного кешування немає - 6502 завжди отримував доступ до DRAM безпосередньо. Сучасні системи мають кеші SRAM, які ускладнюють передбачення стану - хоча, можливо, ще можливо передбачити поведінку системи з кешем, це, безумовно, складніше.
- Жодна інша програма не працює одночасно - програма в картриджі мала повний контроль над системою. Сучасні системи запускають декілька програм одночасно, використовуючи алгоритми недетермінованого планування.
- Тактова швидкість досить повільна, щоб сигнали могли подорожувати по всій системі в часі. У сучасній системі з тактовою частотою 4 ГГц (наприклад) потрібно фотон легких 6,67 тактових циклів, щоб подорожувати довжиною півметрової материнської плати - ви ніколи не могли очікувати, що сучасний процесор взаємодіє з чимось іншим на платі всього за один цикл, оскільки для отримання сигналу на платі потрібно навіть один цикл, щоб навіть досягти пристрою.
- Добре визначена тактова частота, яка рідко змінюється (1,19 МГц у випадку з Atari) - швидкості процесора сучасних систем постійно змінюються, в той час як Atari не може цього зробити, не впливаючи також на телевізійний сигнал.
- Опубліковані терміни циклу - x86 не визначає, скільки часу займає будь-яка його інструкція.
Усі ці речі об'єдналися, щоб створити систему, де можна було скласти набори інструкцій, які потребували б точної кількості часу - і для цього додатка саме цього вимагали. Більшість систем не мають такої ступеня точності просто тому, що в цьому немає потреби - обчислення або виконуються після їх завершення, або якщо потрібна точна кількість часу, незалежний годинник можна запитати. Але якщо потреба є правильною (як, наприклад, у деяких вбудованих системах), вона все одно може з’явитися, і ви зможете точно визначити, скільки часу ваш код запускається в цих середовищах.
І я також повинен додати велику масову відмову від відповідальності, що все це стосується лише побудови набору інструкцій по збірці, які займуть точну кількість часу. Якщо ви хочете зробити якийсь довільний збір, навіть у цих умовах, і запитати "Скільки часу потрібно виконати?", Ви категорично не можете цього зробити - це проблема зупинки , яка виявилася нерозв'язною.
РЕДАКЦІЯ 1: У попередній версії цієї відповіді я заявив, що Atari 2600 не мав можливості повідомити процесору про те, де він знаходиться в телевізійному сигналі, що змусило його з самого початку вести підрахунок та синхронізацію всієї програми. Як вказувалося мені в коментарях, це стосується деяких систем, таких як ZX Spectrum, але це не стосується Atari 2600, оскільки він містить апаратний реєстр, який зупиняє процесор до тих пір, поки не настане наступний горизонтальний інтервал гасіння, а також функція запускати інтервал вертикального затулення за бажанням. Отже, проблема підрахунку циклів обмежена кожною лінією сканування і стає точною лише тоді, коли розробник бажає змінити вміст у міру нанесення.