3.Как на ассемблере NASM описать неинициализированный массив структур данных?
4.Как на ассемблере NASM описать инициализированный массив структур данных?
Лабораторная работа №7
Содержание работы. Изучение организации кадра стека подпрограмм и его использования для рекурсивного выполнения функций.
Предварительные сведения.
Наиболее универсальным способом передачи аргументов подпрограмме является построение и использование стекового кадра подпрограммы, называемого также в некоторых технических руководствах стековым фреймом подпрограммы. Стековый кадр содержит всю информацию, связанную с выполнением текущего вызова подпрограммы. При рекурсивном вызове подпрограммы ее кадры, аналогичные по строению, размещаются в стеке один над другим.
Стековый кадр состоит из области аргументов вызова, адреса возврата в программу, сделавшую вызов, из поля сохранения служебного регистра базирования кадра и из области локальных переменных текущего выполнения подпрограммы. Кроме того, сверху в стековый кадр укладываются сохраняемые регистры и все данные временного хранения в стеке при выполнении подпрограммы.
В архитектуре IA32 регистр базирования кадра называется EBP. При использовании 32-битных аргументов вызова они указываются через регистр базирования как [EBP+8], [EBP+12] и т.д. Причем это правило соответствие имеет место только, если в самом начале машинного кода подпрограммы размещаются последовательно команды
push EBP mov EBP, ESP
Их использование является правилом построения процедур стандартной внутренней структуры. Это правило неукоснительно используется большинством трансляторов и на него даже ориентируются стандартные отладчики.
В дополнении к указанному правилу, в самом конце действий подпрограммы должны быть записаны машинные команды
mov ESP, EPB pop EBP
ret
Команда возврата RET при этом может содержать в качестве параметра число байт в области аргументов вызова, тогда она освобождает сама эту область и не требуется возлагать действия по освобождению области аргументов на вызывающую программу. Команда
mov ESP, EPB
в этом фрагменте может быть заменена на команду ADD ESP, длина области локальных переменных
31
если эти локальные переменные используются в подпрограмме и под них распределялась область в составе кадра стека. Если же такая область не распределялась, то в указанных командах нет необходимости.
Задание. Построить ассемблерную программу, использующую процедуру вычисления функции Аккермана. Эта функция задается реккурентными соотношениями
A(0,M)=M+1; A(N,0)=A(N-1,1); A(N,M)=A(N-1, A(N,M-1))
и естественный способ ее вычисления заключается в рекурсивных вызовах вычисляющей процедуры. Процедура вычисления функции Аккермана должна использовать передачу аргументов через кадр стека, а результат - по стандартному соглашению. Главная часть программы должна вводить числовые значения аргументов M и N, а затем обращаться к процедуре вычисления функции. Результат выводиться на экран. При отладке начинать проверку работы с очень небольших значений, в частности полагая N<3, иначе есть риск, не дождаться результата за приемлемое время.
Контрольные вопросы.
1.Как через регистр базового указателя кадра процедуры обозначаются аргументы вызова процедуры; приведите пример.
2.Как через регистр базового указателя кадра процедуры обозначаются локальные аргументы процедуры?
3.Что в кадре процедуры обозначает операнд, записанный в виде [EBP+4]?
4.Что в кадре процедуры обозначает операнд, записанный в виде [EBP]?
5.Чем отличаются соглашения по укладке аргументов в стек в языке Си и в языке Паскаль?
6.Чем отличаются соглашения по очистке стека от аргументов в языке Си и в языке Паскаль?
Содержание работы. Изучение архитектурных средств для эффективной работы со строковыми данными и построение процедур обработки текстовых строк.
Предварительные сведения. Основные материалом для данной работы служит глава шестая учебного пособия [20].
Задание. Разработать программу, которая осуществляет ввод двух строк текста, поиск в них начала содержательной части путем поиска первого не пробела и сравнение этих содержательных частей до последующего пробельного символа. (Пробельным символом может быть обычный пробел или символ конца строки.) Программа должна выдавать результат сравнения - совпадают рассматриваемые части текста или не совпадают. Программа должна использовать процедуры для отдельных действий и строковые команды.
Контрольные вопросы.
32
1.Чем отличается поиск в строке с помощью строковой команды SCASB, когда этот поиск ведется с начала строки и когда такой поиск требуется вести с конца строки.
2.Как правильно перенести текст строки на новое место, которое частично занимает и исходное размещение строки.
Лабораторная работа №9
Содержание работы. Изучение низкоуровневых программных средств для построения динамических структур данных.
Предварительные сведения. Для построения динамических структур данных языки высокого уровня используют указатели. Практика программирования формирует навыки работы с указателями, но их действительное понимание возникает при овладении представлением на нижнем уровне, доступном через использование отладчиков и через программирование на ассемблере.
Для студентов важно сосредоточить внимание не на формальных определениях и правилах, а на особенностях применения внутренних машинных кодов как для собственно данных, так и для адресации данных. Использование указателей основано, в конечном счете, на косвенно регистровой адресации машинной архитектуры или, в общем случае, на косвенной адресации данных. Последний вариант при меняется не в каждой архитектуре процессоров, в частности, в архитектуре IA32 его нет. Поэтому текущая лабораторная работа будут ориентировать обучение исключительно на косвенно регистровую адресацию или производные от нее базовые и базово индексные способы адресации.
В конечном счете, использование машинного кода в качестве значения или адреса зависит на нижнем уровне программирования исключительно от использования того или иного варианта машинной команды или использования команд, которые содержательно обеспечивают переход от адреса к данным, либо же в обратном направлении. Причем переход от данных к их адресу возможен только при программировании с использованием символических имен, поскольку данные, о которых не известно их наименование в исходном представлении, не дают транслятору информации о их размещении. В частности, они могут размещаться в регистре.
Содержательную связь между использованием указателей и данных в языке Си и внутренними обозначениями дает следующий пример. Пусть в программе на языке Си описаны переменные x, y и указатели p1, p2, использованные в следующем фрагменте программы:
int x, y;
int *p1, *p2;
имяподпрограммы () { …
x=5;
p1=&x;
y=*p1;
. . .
33
p2=p1;
. . .
}
Соответствующими фрагментами программы на ассемблере будет
SEGMENT .bss x RESD 1
y RESD 1 p1 RESD 1 p2 RESD 1
. . .
SEGMENT .text
. . .
mov [x], 5 ; числовое значение 5 заносится в именованную область x
mov DWORD [p1], x ; адрес области x заносится в именованную область p1 mov EAX, [p1] ;содержимое области p1, т.е. адрес x, заносится в регистр
EAX
mov EDX, [EAX] ; во втором операнде содержимое регистра EBX используется как адрес в интерпретации косвенно регистрового способа адресации; значение
собственно операнда, извлекаемое в этом способе адреса-
ции,
заносится в регистр EDX
mov [y], EDX ; результат заносится в область y
. . .
mov ECX, [p1] ; значение p1 заносится в регистр ECX mov [p2], ECX ; значение из регистра ECX заносится
; в именованную область p2
Для сравнения различия действий доступа к значению данных по указателю на них (в форме *указатель) и действия со значением самого указателя как изменяемого информационного объекта в последних двух командах приведена реализация операнда p2=p1;
Убедиться в том, что именно такая связь между текстом на языке Си и ассемблерной реализацией имеет место, можно подвергнуть трансляции исходный текст, помещенные например, в файл prog.c с помощью командного вызова
bcc33 -S prog.c
Здесь используется опция -S , которая формирует результат трансляции в виде ассемблерного файла prog.asm.
Задание. Разработать программу работы со связанным списком, элементы которого состоят: из 8-символьного поля имени, однобайтового поля "возраста" и 4-байтового поля адреса следующего элемента списка. Элементы в списке должны быть упорядочены по алфавитному порядку хранимых в нем имен. Программа должна по запросам в диалоге с пользователем реализовывать следующие функции: вставлять в список задаваемый элемент (задаются значения полей имени и возраста), удалять из списка элемент с заданным именем, выводить список
34
на экран. Память для размещения списка для упрощения построения программы зарезервировать в сегменте данных, задавая именованной константой максимальное число элементов списка в виде последовательности экземпляров структур для языка ассемблера или просто последовательности групп байтов.
Лабораторная работа №10
Содержание работы. Изучение средств и методов построения и использования библиотек динамической компоновки в операционных системах типа Windows.
Предварительные сведения.
Библиотеки DLL создает системный компоновщик - почти также как он создает исполняемые файлы. Для того, чтобы компоновщику создавать исполняемый файл (с расширением EXE) или библиотеку DLL (с расширением DLL) требуются специальные указания. Для задания таких указаний сложилось два основных подхода: в одном они задаются как опции при вызове компоновщика, в другом включаются в состав вспомогательного файла определения компоновки с расширением DEF, который задается в качестве соответствующего файла-пара- метра при вызове компоновщика. Стандартный вызов компоновщика в командной строке по второму варианту используется в продукции Inprise/Borland и имеет вид
Имя_компоновшика опции объекфайлы, результ, карта, список_библк, def-файл
где результ обозначает имя исполняемого файла или DLL-библиотеки, карта обозначает имя файла карты загрузки, список_библк обозначает перечисление через пробел имен статических библиотек, используемых при компоновке, а defфайл обозначает файл определения параметров результирующего файла. Часть конструкции вызова компоновщика содержит перечисление используемых объектных файлов, причем они задаются перечислением их имен через пробелы или символ + (символ плюс).
Имя компоновщика в указанных системах для 16-битного варианта есть TLINK, а для 32-битного - TLINK32. Все компоненты - файлы в командной строке вызова компоновщика, как правило, задаются без расширений, если они имеют стандартные расширения. Явное задание имен файлов вместе с расширениями встречается очень редко. Заметим, что файл карты загрузки имеет расширение MAP, статические библиотеки - расширение LIB. В любом варианте применение динамической компоновки в полном объеме требует как создания DLL-библио- тек, так и создание приложений (исполняемых программных файлов), которые эти библиотеки используют.
Существенным дополнением к обычной подпрограмме, при реализации последней в составе DLL является дополнительная процедура, вызываемая по стартовому имени ..start. Эта процедура при реализации на ассемблере должна возвращать ненулевое значение в регистре eax и ее можно вынести в отдельный исходный и объектный файл. Такая ситуация оказывается очень удобной, так как позволяет один и тот же исходный текст использовать и для DLL-библиотек и для обычных статических библиотек. Особенности появляются при изготовлении ре-
35