Программы, которые изобилуют ветвлениями и переходами во всех направлениях, нежелательны во
всех смыслах, а в случае работы с процессорами серий 80 х 86 и 80 х 88 — особенно. Это является напутствием, цель которого — побудить программистов
на ассемблере и тех, кто оптимизирует компиляторы, должным образом структурировать программы.
В этом случае существуют свои проблемы, но сначала
рассмотрим некоторые особенности процессоров
фирмы Intel.
Быстродействие данных процессоров в значительной мере зависит от их архитектуры, основанной на простой конвейерной схеме, которая содержит три компоненты: шинный интерфейс (BIU — Bus Interface Unit),
очередь упреждающей выборки и исполнительный модуль (EU — Execution Unit). Если шина памяти в нерабочем состоянии, например в случае выполнения команды
из многих циклов, с операндами, находящимися в регистрах, шинный интерфейс получает байты команд из памяти и располагает их в очередь упреждающей выборки,
последовательно продвигаясь дальше от текущего расположения командного счетчика центрального процессора. Когда исполнительный модуль заканчивает выполнение очередной команды, он ищет следующую команду
в ряде упреждающей выборки: если она есть, к ее рас-
шифровке можно приступать непосредственно, не обращаясь лишний раз к памяти.
Каждый раз, когда исполнительный модуль уточняет команду перехода или вызова, он аннулирует текущее содержимое очереди упреждающей выборки и определяет новый счетчик команд. Затем
шинный интерфейс снова выбирает байты команд, начиная при этом с нового адреса, и заносит их в очередь.
Исполнительный модуль в это время должен «простаивать», пока не будет определена полная команда.
При этом все обращения к памяти, необходимые для
исполнения команды перехода по новому адресу, тоже
влияют на выборку следующих команд из памяти. Может пройти много времени, прежде чем шина опять заполнит очередь упреждающей выборки, так, чтобы
применяемый модуль мог работать с наибольшей скоростью. Кроме того, размер очереди командных байтов не одинаков для разных моделей центральных процессоров. Он составляет только 4 байта в ранних
моделях и 32 байта в современных компьютерах. Таким
образом, крайне сложно предсказать время исполнения для данных последовательностей команд исходя из
количества тактов и длин в байтах. Также состояние
очереди команд для разных типов центральных процессоров определяется «выравниванием» команд. Шинный
интерфейс обязан выбирать команды по разрядности
адресной и информационной частей шины.
Исходя из всего вышесказанного, можно сформулировать первое правило оптимизации переходов и вызовов: необходимо проверить, что их точки назначения
попадают в подходящие границы адресов для того типа
процессора, на котором данная программа будет работать чаще всего. При этом следует добавить подходящий атрибут выравнивания (WORD или DWORD) в объявления сегментов, а также вставить директиву ALIGN
перед каждой меткой.