Организация ЭВМ и систем

 

Лабораторная работа ?2

Изучение ассемблерного листинга программы

(архитектура x86/x86-64)

 

Цель:

1)      Познакомиться с программной архитектурой x86/x86-64,

2)      научиться читать ассемблерный листинг программы для x86/x86-64 и проводить его простейший анализ.

 

Язык ассемблера привязан к архитектуре процессора. Команды ассемблера напрямую отображаются в команды процессора. Поэтому, рассматривая ассемблерный код программы, можно с большой долей уверенности судить о том, как программа будет реально исполняться.

Некоторые операции, такие как некоторые ветвления и обращения к памяти, выполняются намного дольше других команд. Оптимизирующий компилятор старается сформировать максимально эффективный код, т.е. который исполняется наиболее быстро. Вот некоторые действия, которые компилятор выполняет с целью улучшения кода:

·        Избежание частых обращений в медленную оперативную память. Компилятор старается расположить как можно больше данных в регистрах.

·        Переупорядочение инструкций процессора

·        Устранение зависимостей по данным, чтобы иметь больше свободы при переупорядочивании инструкций.

·        Исключение недосягаемого кода.

·        Устранение лишних и избыточных вычислений и вызовов функций.

·        Удаление неиспользуемых переменных.

·        Вычисление выражений на этапе компиляции, выполнение алгебраических преобразований с целью упростить выражение.

·        Устранение ветвлений путем дублирования кода, использования условного присваивания.

·        Оптимизация ветвлений:

·        Замена долгих операций на более быстрые (например: деление -> умножение -> сложение -> побитовый сдвиг).

·        Оптимизация циклов:

·        Переупорядочивание функций.

·        Встраивание функций с целью устранения ветвлений при вызове функции, для возможности переупорядочить инструкции на границе тела функции и вызывающего кода.

·        Оптимизация для конкретной архитектуры, использование специальных расширений (MMX, 3DNow!, SSE, SSE2, ...).

 

Задание

Задание следует выполнять на сервере solarka с помощью компилятора Sun Studio C Compiler 5.8 (команда cc). Тестовую программу (из первой лабораторной работы) скомпилировать и запустить с различными ключами оптимизации:

 

Уровни оптимизации

Архитектура x86

Архитектура x86-64

Без оптимизации

 

-xarch=amd64a

Уровень 1

-xO1

-xO1 -xarch=amd64a

Уровень 2

-xO2

-xO2 -xarch=amd64a

Уровень 3

-xO3

-xO3 -xarch=amd64a

Уровень 4

-xO4

-xO4 -xarch=amd64a

Уровень 5

-xO5

-xO5 -xarch=amd64a

Максимизировать скорость исполнения

-fast

-fast -xarch=amd64a

 

Для каждой архитектуры выбрать вариант оптимизации, работающий наиболее быстро. Сгенерировать ассемблерные листинги для следующих вариантов оптимизации:

-        Архитектура x86 без оптимизации,

-        Архитектура x86 с минимальным временем работы,

-        Архитектура x86-64 без оптимизации,

-        Архитектура x86-64 с минимальным временем работы.

В каждом ассемблерном листинге:

1.      Распознать вычислительную функцию, сопоставить команды языка Си с командами ассемблера.

2.      Локализовать обращения в память, которые происходят при выполнении вычислительной функции. Определить позиции в исходной программе на Си, в которых происходят обращения в память. Посчитать общее число обращений в память при выполнении вычислительной функции (функция от N - параметра задачи).

3.      Определить, какие переменные и параметры вычислительной функции отображены на регистры, и какие размещены в памяти. Какие регистры используются для реализации вычислений (регистры общего назначения, регистры x87, MMX, XMM).

4.      Описать видимые изменения в ассемблерном коде программы при переходе от неоптимизированного листинга к оптимизированному. Описать какие оптимизационные преобразования выполнил компилятор. Например:

-        были убраны ненужные инструкции,

-        переменные стали располагаться на регистрах,

-        стали использоваться другие инструкции,

-        инструкции стали располагаться в другом порядке,

-        цикл развернулся сколько-то раз,

-        функция не вызывается с помощью call, а подставляется ее код,

-        и т.п.

Где возможно, приводить конкретные примеры ассемблерных команд из листинга.