- •6. Лекция. Язык программирования ассемблер ia-32 (Intel Architecture -32bit)
- •6. Язык программирования ассемблер ia-32
- •6.1. Структура программы на языке ассемблер
- •6.2. Директивы языка ассемблера ia-32
- •6.2.1. Псевдокоманды определения переменных
- •6.2.2. Организация программы
- •6.3. Управление потоком выполнения программы
- •6.3.1. Условные переходы и флаги кодов условий
- •6.3.2. Команды сравнения
- •6.3.3. Безусловный переход
- •6.4. Логические команды, команды сдвига и циклического сдвига
- •6.4.1. Логические операции
- •6.4.2. Операции сдвига и циклического сдвига
- •6.4.3. Программа упаковки цифр
- •6.5. Другие команды
- •6.5.1. Вычитание
- •6.5.2. Команды умножения и деления
- •Imul reg,src(исходный)
- •Imul src и mul src
- •Idiv src и div src
- •6.5.3. Команды мультимедийного расширения
- •6.5.4. Векторные команды
- •6.6. Подпрограммы
- •6.6.1. Вложенность подпрограмм и стек процессора
- •6.6.2. Организация стека
- •6.6.3. Передача параметров
- •6.7. Примеры программ
- •6.7.1. Программа для вычисления скалярного произведения двух векторов
- •6.7.2. Программа сортировки байтов
- •6.7.3. Подпрограммы для вставки и удаления элементов связного списка
- •6.8. Различия между программами в ехе - и сом - файлах
- •6.8.1. Пример программы типа сом
- •6.8.2. Пример программы типа ехе
6.6.3. Передача параметров
Вызывая подпрограмму, программа должна передать ей параметры (операнды), которые будут использоваться в вычислениях, или же их адреса. Закончив свою работу, подпрограмма вернет другие параметры — результаты вычислений. Такой обмен информацией между вызывающей программой и подпрограммой называется передачей параметров. Передача параметров может выполняться несколькими способами. Например, параметры можно помещать в регистры или в память, откуда подпрограмма сможет их считать. В качестве альтернативы параметры можно поместить в стек процессора, используемый для хранения адресов возврата.
Использование регистров процессора — способ простой и эффективный. На рис. 6.7 показано, как реализовать программу, выполняющую сложение последовательности чисел, в виде подпрограммы с передачей параметров через регистры. Длина последовательности n, информация о которой хранится в памяти по адресу N, и адрес первого числа, NUM1, передаются подпрограмме через регистры ECX и EBX. Вычисленная подпрограммой сумма возвращается вызывающей программе через регистр EAX. Соответствующую часть вызывающей программы составляют первые четыре команды из числа представленных на рис. 5.19. Первые две команды загружают в регистры ECX и EBX значения N и NUM1. Команда Call выполняет переход к подпрограмме, начинающейся по адресу LISTADD. Кроме того, эта команда помещает в стек процессора адрес возврата из подпрограммы. Подпрограмма вычисляет сумму и помещает ее в регистр EAX. После возврата из подпрограммы вызывающая программа сохраняет эту сумму в памяти по адресу SUM.
Таким образом, регистры ЕВХ, ЕСХ и ЕАХ используются для передачи параметров. Регистр EDI подпрограмма при выполнении сложения задействует в качестве индексного регистра, поэтому его содержимое должно сохраняться и восстанавливаться при помощи команд PUSH и POP. Подпрограмма вызывается командой
CALL LISTADD
Первым делом эта команда проталкивает в стек адрес возврата, а затем выполняет переход по адресу LISTADD. Содержимое стека после сохранения в нем содержимого регистра EDI показано на рис. 6.7, б. Адрес возврата в нашем примере — это адрес команды MOV, непосредственно следующей в вызывающей программе за командой CALL. Команда RET возвращает управление вызывающей программе, выталкивая из стека содержимое указателя команды EIP.
а
б
Рис. 6.7. Программа с рис. 5.8, переписанная в виде подпрограммы для процессоров IA-32; параметры передаются через регистры: вызывающая программа и подпрограмма (а);
содержимое стека после сохранения значения EDI в подпрограмме (б)
На рис. 6.8 показан еще один вариант этой же программы, в котором параметры передаются подпрограмме через стек. Параметры NUM1 и N проталкиваются в стек двумя командами PUSH в вызывающей программе. После выполнения команды CALL вершина стека располагается на уровне 2. Регистры EDI, ЕАХ, ЕВХ и ЕСХ используются так же, как в подпрограмме на рис. 5.7. Их значения сохраняются в стеке, затем в них загружаются начальные значения и параметры. Эту работу выполняют первые 8 команд подпрограммы. В результате вершина стека оказывается на уровне 3. После сложения чисел при помощи цикла из четырех команд сумма помещается в стек на место параметра NUM1. Выполнив команду RET, команды вызывающей программы ADD и POP удаляют из стека параметр N и помещают результирующую сумму в память по адресу SUM, возвращая вершину стека на уровень 1.
а
б
Рис. 6.8. Программа с рис. 6.7, а, переписанная в виде подпрограммы для процессоров IA-32 (параметры передаются через стек): вызывающая программа и подпрограмма (а);
содержимое стека после сохранения значения EDI в подпрограмме (б)
В завершение темы вызова подпрограмм мы рассмотрим пример обработки вложенных вызовов. На рис. 5.9 приведен код программы на языке ассемблера IA-32, иллюстрирующей пример обработки вложенных вызовов. Стековые фреймы обоих подпрограммы вы видите на рис. 5.10. Указателем на фрейм служит регистр ЕВР. В наборе команд IA-32 имеются команды PUSHAD и POPAD, с помощью которых можно сохранить в стеке и восстановить из него все восемь регистров общего назначения, но в программе на рис. 5.9 мы предпочли воспользоваться отдельными командами PUSH и POP, поскольку в подпрограммах задействована только половина всех регистров.
Рис. 6.9. Вложенные подпрограммы на языке ассемблера IA-32
Рис. 6.10. Стековые фреймы для программы, представленной на рис 6.9. (Вершина стека ESP)