Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

Labs / 6_Procs / Lab6

.pdf
Скачиваний:
19
Добавлен:
16.04.2013
Размер:
268.18 Кб
Скачать

1

Лабораторная работа по курсу "Организация ЭВМ и систем"

Процедуры. Ассемблерные модули в программах на языках высокого уровня

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

Задание 1. Простая процедура в ассемблерной программе

1.1. Процедура в общем модуле. Напишите 16-битную программу (работающую в реальном режиме микропроцессора Intel) prog1.asm, которая содержит процедуру sum. Процедура sum принимает в стеке три параметра - 16-битных числа, вычисляет их сумму и возвращает ее в регистре ax. Оформите по стандартным правилам пролог и эпилог процедуры. Главная программа вызывает процедуру sum(A,B,C) и записывает результат в ячейку c именем S.

Выполните программу в отладчике и проверьте содержимое стека, записанное Вами при домашней подготовке к работе. Поясните, как получить доступ к параметрам в процедуре, к локальным переменным процедуры (если бы они были)? Где происходит очистка стека в Вашей программе и при помощи каких команд? *Расшифруйте код команды call sum.

1.2. Процедура в отдельном модуле. Модифицируйте программу prog1.asm (дайте ей имя prog2.asm): перенесите процедуру sum в отдельный модуль sum.asm, изменив тип процедуры на far. При этом не забудьте указать в главной программе директиву extrn sum:far, в модуле sum.asm - директив public sum. Модуль sum.asm должен завершаться директивой end без параметров. Командная строка для компоновки программы из нескольких объектных модулей имеет следующий вид:

tlink prog2 sum или tlink prog2 sum, example

В первом случае имя исполнимого файла будет совпадать с именем первого объектного модуля (prog2.exe), во втором случае именем исполнимого файла будет example.exe.

Выполните программу в отладчике и проверьте содержимое стека, записанное Вами при домашней подготовке к работе. Объясните в отчете отличия содержимого стека от полученного в п. 1.1. *Будет ли программа работать, если присвоить процедуре sum тип near?

Задание 2. Ассемблерная процедура в приложении Delphi

2.1. Создание консольного приложения Delphi. ОС Windows работает в защищенном ре-

жиме (protected mode) микропроцессора Intel и плоской модели памяти (flat memory model). При этом ассемблерный код программ проще, чем в реальном режиме, т.к. все 32-битные адреса являются адресами типа near и в прикладных программах не нужно заботиться о содержимом сегментных регистров. Консольное приложение Windows, хотя и работает с окном консоли, напоминающим экран программ MS DOS, является полноценным 32-х битным приложеним ОС Windows, хотя и без привычного для Windows оконного интерфейса.

1.Запустите Delphi из стартового меню: Пуск|Программы|Borland Delphi 5|Delphi 5.

2.В Delphi создайте консольное приложение: File|New, выберите пункт Console Application.

3.Наберите текст программы (рис. 1), учитывая, что некоторые из этих строк уже сгенерированы Delphi. В этой программе описана функция Calc, которая принимает пять чисел A, B, C, D, E типа INTEGER, вычисляет результат по формуле (A+B)-(C+D)+E+loc, и возвращает его как значение типа INTEGER.

4.Сохраните проект в Вашей папке на диске D:\ под именем Ex1.

5.Выполните приложение: Run|Run или <F9> или кнопка на панели инструментов Delphi.

2.2. Изучение ассемблерного кода программы.

1.Запустите приложение в отладчике: Run|Trace Into или <F7> или кнопка .

2.Перейдите в окно CPU отладчика: View|Debug Windows|CPU.

3.Объясните в отчете, каким способом в Delphi осуществляется передача параметров в процедуру/функцию, как возвращается результат функции, где происходит очистка стека. Примите во внимание, что первые три переменные, A, B и C, будут находиться в главной программе в регист-

2

рах EBX, ESI и EDI соответственно. *Объясните, как следует изменить заголовок функции Calc, чтобы все параметры передавались через стек?

program Project1;

 

{$APPTYPE CONSOLE}

 

uses

 

SysUtils;

 

var

integer;

A, B, C, D, E:

ResVal: integer;

 

function Calc (A1,A2,A3,A4,A5: integer): integer; var

loc: integer;

begin loc := 5;

Calc := (A1 + A2) - (A3 + A4) + A5 + loc; end;

begin

WRITELN ('Enter five integer numbers'); READLN (A,B,C,D,E);

ResVal := Calc(A,B,C,D,E); ResVal := ResVal + 1; WRITELN('Result = ',ResVal); READLN;

end.

Рис. 1. Текст консольного приложения наязыке Object Pascal

2.3. Создание ассемблерного модуля.

1. Наберите текст модуля с процедурой Calc на языке ассемблера (на рис. 2). Сохраните модуль в файле Calc.asm. Запишите прокомментированный Вами текст модуля в отчет.

.386

PUBLIC Calc

CODE segment USE32 PUBLIC

Calc PROC

... ... ... ... ... ... ...

ENDP ; конец процедуры CODE ends ; конец сегмента

end ; конец модуля

Рис. 2. Шаблон для ассемблерного модуля

ПРИМЕЧАНИЕ. Тело процедуры Calc можно взять из окна отладчика.

2.4. Включение ассемблерного модуля в приложение Delphi.

1.Откомпилируйте модуль Calc.asm компилятором TASM.

2.В среде Delphi в тексте программы Ex1:

Уберите тело функции Calc, т.к. теперь эта функция находится в модуле Calc.obj.

Добавьте атрибут external в заголовок функции Calc. Этим мы укажем компилятору, что функция Calc находится в другом модуле:

function Calc(…): integer; external;

Перед заголовком функции Calc добавьте строку с директивой компилятора {$L Calc} или {$LINK Calc} , которая заставит компилятор в процессе компоновки присоединить к проекту объектный модуль Calc.obj. Если объектный модуль находится в другой папке, то в директиве укажите полное имя файла Calc.obj.

Сохраните измененный проект под именем Ex2. 3. Выполните и отладьте приложение Ex2.

ПРИМЕЧАНИЕ. Если в процессе отладки Ex2 Вы измените только файл Calc.obj, то при запуске проекта Ex2 будет выполнен старый файл Ex2.exe, т.е. Вы не сможете включить в приложение

3

сделанные Вами в Calc изменения. В этом случае следует сначала выполнить в Delphi команду

Project|Build Ex2, а затем - Run|Run.

Задание 3. *Включение ассемблерного модуля в программу на языке С++

Напишите программу Ex3 на языке С++ в Borland C++ Builder или MS Visual C++,

вызывающую простую ассемблерную функцию. Функция получает два-три параметра и возвращает значение целого типа.

При включении ассемблерного модуля в проект, написанный на языке C++ следует учитывать следующее:

В системах Borland C++ Builder / MS Visual C++ ассемблерный модуль *.asm можно включить в проект, пользуясь средствами соответствующей системы. При сборке проекта ассемблер (TASM или MASM) будет вызван автоматически, т.к. он входит в стандартную поставку системы.

Ассемблерная функция не должна изменять содержимое регистров EBX, ESI и EDI, поскольку они используются для хранения регистровых переменных.

Имя процедуры в ассемблерном модуле следует начинать с символа подчеркивания "_", поскольку компоновщик С ко всем внешним именам добавляет этот символ. (Это справедливо не для всех компиляторов.) Кроме того, это имя должно быть набрано с использованием того же регистра клавиатуры, что и соответствующее имя в программе на С++.

Прототип функции в программе на С++ должен начинаться с квалификатора external "C" Этим мы указываем, что имя внешней функции должно формироваться по правилам языка С (см. выше), а не С++. Если не указать "C", то имя внешней функции будет непредсказуемым (из-за обработки перегрузки функций).

По умолчанию параметры передаются в стеке в обратном порядке, справа налево, т.е. самым последним помещается в стек самый первый параметр. При этом многие компиляторы могут помещать часть параметров в регистры (Borland - 3 параметра, Microsoft - 2 параметра), но при явном указании квалификатора _fastcall в прототипе функции.

Функция возвращает значение целого типа и указателя в регистре EAX, вещественного типа - в регистре сопроцессора ST0.

Если используется соглашение по умолчанию (cdecl), то стек очищает вызывающая программа, т.е. в этом случае следует использовать команду ret без числового аргумента. Примерный вид главной программы и ассемблерного модуля:

extern "C" unsigned asmproc

.486

(unsigned a, unsigned b);

PUBLIC asmproc

void main (void)

CODE segment USE32 PUBLIC

{ unsigned a;

_asmproc proc

a=asmproc(5,6);

..

..

_asmproc endp

}

CODE ends

 

end

Порядок выполнения лабораторной работы

1.Выполните задания 1-2. Работу программ prog1, prog2 и Ex2 покажите преподавателю.

2.Оформите отчет и защитите работу.

Требования

1.При подготовке к лабораторной работе (дома) запишите в отчет а) прокомментированные тексты программ prog1.asm, prog2.asm + sum.asm и приложения Delphi Ex2; б) вид стека при входе в процедуру sum и после выполнения пролога (для prog1.asm и prog2.asm).

2.При выполнении работы включите в отчет все требуемые пояснения.

* Необязательные задания. Оцениваются дополнительно, если студент полностью выполнил обязательные задания.

---------------------------------------------------------------------------------------------------

© Лабораторная работа подготовлена Л.В. Илюшечкиной

Соседние файлы в папке 6_Procs