Ну вот например, шлю тестовую программу на си и результат ее компиляции в асм. Программа состоит из двух простых функций: gcd для поиска наибольшего общего делителя; и recupow для возведения в степень с помощью рекурсии (хотел посмотреть, как компилируется рекурсия).
Замечания следующие:
1) Генерируется код для инициализации глобальных переменных (строки 47-65 асм-файла). Вместо этого можно было бы иметь сегмент инициализированных данных, эта концепция поддерживается многими компоновщиками.
2) Код инициализации данных чрезвычайно неэффективный:
LD IY, adr
LD (IY),data
3) Для сравнения двух однобайтовых переменных (строки 84-87 асм-файла) используется команда SUB, а не CP. В результате портится значение аккумулятора, которое далее по тексту программы приходится восстанавливать.
4) Весь цикл функции gcd (строки 84-104 асм-файла) реализован без использования регистров для локальных переменных, все данные сохраняются в памяти посредством индексной адресации. Мне удалось разместить переменные на регистрах только если объявить их локальными, скопировать в них значения аргументов функции, а в цикле работать с локальными переменными. Что ж - спасибо и на этом, хотя с семантической точки зрения разницы быть не должно, и оптимизатор, в идеале, должен генерировать одинаковый код в обоих случаях.
5) Для функции recupow, сравнение одного и того же числа с разными значениями, строки 121, 129 асм-файла. Во-первых, выполнение OR A не портит значение аккумулятора, поэтому восстанавливается он без необходимости. Во-вторых, сравнение с единицей командой SUB 1. Почему не CP? Почему не DEC? Тем более что далее по тексту программы значение аккумулятора снова восстанавливается из памяти (строка 136) и снова уменьшается на единицу, на этот раз командой DEC.
Засылка однобайтового числа на стек обычно выполняется командами PUSH AF / INC SP. Этим экономится 1 байт на стеке за счет потери тактов на команду INC SP и, возможно, DEC SP при удалении со стека аргументов после возврата функции, если их число было нечетным.
Однако в строках 138-140 асм-файла аргумент засылается на стек почему-то посредством LD D,A / PUSH DE / INC SP. Я не нашел этому разумного объяснения.
Путем некоторых шаманских действий с программами - таких как перемена местами операндов при сравнении на неравенство (!) - мне удавалось иногда повысить эффективность генерируемого кода. Но если писать на Си или другом языке высокого уровня, изначально учитывая особенности оптимизатора - то проще уж сразу на ассемблере писать программы.





Ответить с цитированием
