1: < (a, b)
можно построить по
mov eax, a
cmp eax, b
jl @M1_1
xor eax, eax
jmp @M1_2
@M1_1: xor eax, eax
inc eax
@M1_2:
которая будет обеспечивать запись в регистр аккумулятора (eax) логического результата операции сравнения (0 – «ложь», 1 – «истина»).
Однако, как уже было сказано, большое количество операций передачи управления не способствует эффективности выполнения программы. К тому же рассмотренный выше подход порождает много лишних команд. Как правило, в процессорах есть команды, позволяющие организовать либо прямой обмен между регистром флагов и регистром аккумулятора, либо обмен данными через стек. В процессорах типа Intel 80x86 это команды группы set<*>, где <*> зависит от необходимого флага [41, 44]. Тогда для того же самого примера порядок команд будет иным:
mov eax, a
cmp eax, b
setl al
and eax, 1
В предлагаемом генераторе кода используется именно такой подход. А в остальном порождение кода для операций сравнения не отличается от порождения кода для прочих линейных операций.
Еще несколько слов необходимо сказать о триаде условного перехода IF. Для нее ситуация иная, чем для операций сравнения – чтобы выполнить условный переход, надо установить регистр флагов на основе регистра аккумулятора. Для этого можно воспользоваться простейшей командой процессора для сравнения регистра аккумулятора с ним самим, например:
test eax, eax
однако эффективность результирующего кода можно увеличить, если учесть, что триаде IF всегда предшествует либо триада сравнения, либо триада логической операции, а следовательно, при выполнении кода, порожденного для этих триад, флаги уже будут установлены соответствующим образом. Тогда нет необходимости порождать дополнительную команду для установки флагов и для триады IF достаточно построить только команду условного перехода по флагу «ноль» (в процессорах типа Intel 80x86 это команда jz).
Но система команд процессоров типа Intel 80x86 имеет одну особенность: команды условного перехода могут передавать управление не далее, чем на 128 байт вперед или назад от места команды. В момент генерации кода для триады IF, как правило, не известно, будет ли передача управления происходить в пределах 128 байт кода или выйдет за рамки данного ограничения. Чтобы обойти это ограничение, передачу управления можно организовать с помощью двух команд: сначала команда условного перехода по обратному условию «не ноль» передает управление на локальную метку, а потом команда безусловного перехода передает управление на требуемую «дальнюю» метку:
jnz @Fx
jmp @Mx
Fx:…
Здесь @Fx – локальная («обходная») метка, а @Mx – та метка, на которую необходимо передать управление. Именно такой подход реализован в разработанном генераторе ассемблерного кода. [11]
Есть еще одна особенность в генерации кода для триады IF: поскольку в разработанном генераторе триад операции сравнения и логические операции обрабатываются как линейные операции, а потому могут быть оптимизированы, первый операнд триады может оказаться константой. При этом триада IF будет выполнять не условный, а безусловный переход на одну из частей условного оператора в зависимости от значения этого операнда. Например, в последовательности операторов:
a:= 1;
if (a<0) b:=0 else b:=1;
первая часть условного оператора (b:=0) никогда не будет выполнена и в результате выполнения оптимизации это станет очевидным (первый операнд триады IF будет равен 0). Генератор ассемблерного кода порождает соответствующий код: если первый операнд равен 0 – команду безусловного перехода; если первый операнд не равен 0, никаких команд для триады IF вообще не порождается.
Можно отметить, что в этом случае вообще нет необходимости порождать код для одной из ветвей условного оператора, что сократит объем результирующего кода, но такая оптимизация требует существенных модификаций всего списка триад, что не предусмотрено в данном примере выполнения работы.
Описание используемого метода оптимизации
Машинно-независимые методы оптимизации
Оба используемых машинно-независимых метода оптимизации – метод свертки объектного кода и метод исключения лишних операций – были описаны при выполнении лабораторной работы № 4, поэтому нет необходимости описывать их здесь повторно. Эти методы оптимизации не зависят ни от входного, ни от результирующего языка, а потому реализующие их алгоритмы, разработанные при выполнении лабораторной работы № 4, могут быть без модификаций использованы в курсовой работе.
Читать дальше
Конец ознакомительного отрывка
Купить книгу