русс | укр

Языки программирования

ПаскальСиАссемблерJavaMatlabPhpHtmlJavaScriptCSSC#DelphiТурбо Пролог

Компьютерные сетиСистемное программное обеспечениеИнформационные технологииПрограммирование

Все о программировании


Linux Unix Алгоритмические языки Аналоговые и гибридные вычислительные устройства Архитектура микроконтроллеров Введение в разработку распределенных информационных систем Введение в численные методы Дискретная математика Информационное обслуживание пользователей Информация и моделирование в управлении производством Компьютерная графика Математическое и компьютерное моделирование Моделирование Нейрокомпьютеры Проектирование программ диагностики компьютерных систем и сетей Проектирование системных программ Системы счисления Теория статистики Теория оптимизации Уроки AutoCAD 3D Уроки базы данных Access Уроки Orcad Цифровые автоматы Шпаргалки по компьютеру Шпаргалки по программированию Экспертные системы Элементы теории информации

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


Дата добавления: 2015-07-23; просмотров: 1020; Нарушение авторских прав


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

Основная программа, использующая подпрограмму, написанную на языке ас­семблера, содержит инициализированный массив, в котором будет определяться максимальное число, а сама программа выводит на экран значение максимально­го числа из этого массива:

const

N = 7;

Massiv: array[1..N] of integer = (1, 2, 3, 2, 10, 7, 2);

 

{$F+}

function Max(var Mas; N:integer); integer; external;

{$L test.obj);

{$F-}

 

begin

Wtiteln(‘Максимальное число массива равно: ’, Max(Massiv, N));

end.

Используя стандартную модель памяти, подпрограмму, определяющую макси­мальное число из массива, можно написать следующим образом:

P386N

Ideal

Model Small, PASCAL

 

DATASeg

 

CODESeg

 

PROC Max Far

Public Max

arg @@AdrMass:dword, @@n:word

uses ds, si, ax, bx, cx

lds si, [@@AdrMass]

mov bx, 8001h

mov cx, [@@N]

cmp cx, 0

jle @@3

@@1: lodsw

cmp ax, bx

jle @@2

mov bx, ax

@@2: loop @@1

@@3: mov ax, bx

ret

EndP

 

End

Параметры передаются в подпрограмму следующим образом. Параметры-значения размеров в 1 байт передаются одним 16-разрядным словом, причем информативным является младший байт, параметры-значения в 2 байта передаются одним 16-разрядным словом, в 4 байта — двумя 16-разрядными словами, параметры типа Real передаются тремя 16-разрядными словами, все остальные параметры-значения (в том числе и трехбайтовые) передаются своими полными адресами. Параметры-переменные и параметры-константы всегда передаются своими полными адресами.

Так как в подпрограмме первый параметр является параметром-переменной, то он передается своим адресом, с помощью которого в дальнейшем и извлекаются элементы массива. Второй параметр подпрограммы — параметр-значение, и он передается своим значением. Первый параметр находится по адресу bp+8, а второй — bp+6. Указанные смещения определяются наличием в стеке адреса возврата, размещенным в стеке значением регистра bp.



Если подпрограмма является подпрограммой-функцией, то возвращаемый параметр передается различным образом в зависимости от своего размера. Параметр размером в 1 байт передается в регистре AL, параметр размером в 2 байта передается в регистре AX, параметр размером в 4 байта — в регистрах DX (старшая часть или адрес сегмента) и AX (младшая часть или смещение), параметры размером в 6 байт (типа Real) — в регистрах DX (старшая часть), BX (средняя часть) и AX (младшая часть). Если функция возвращает значение типа string, то при обращении к функции резервируется память для размещения возвращаемой строки, а адрес этой области размещается в стеке выше всех передаваемых параметров.

В рассматриваемом примере возвращаемый параметр типа integer, и он возвращается в регистре AX.

В подпрограмме, написанной на языке ассемблера, можно использовать подпрограммы, написанные на языке Паскаль. Несколько модифицированная подпрограмма определения максимального элемента массива, которая в случае недопустимого элемента массива (0 или отрицательное число) вызывает подпрограмму, написанную на языке Паскаль для выдачи сообщения.

const

N = 7;

Massiv: array[1..N] of integer = (1, 2, 3, 2, 10, 7, 2);

 

{$F+}

function Max(var Mas; N:integer); integer; external;

{$L test.obj);

{$F-}

 

procedure ErrorReport(N: integer);

begin

Writeln(‘Недопустимое число элементов’, N);

end;

 

begin

Wtiteln(‘Максимальное число массива равно: ’, Max(Massiv, N));

end.

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

P386N

Ideal

Model Small, PASCAL

 

DATASeg

 

CODESeg

 

Extrn ErrorReport: near

PROC Max Far

Public Max

arg @@AdrMass:dword, @@n:word

uses ds, si, ax, bx, cx

lds si, [@@AdrMass]

mov bx, 8001h

mov cx, [@@N]

cmp cx, 0

jg @@1

push bx

push cx

call ErrorReport

pop bx

jmp @@3

@@1: lodsw

cmp ax, bx

jle @@2

mov bx, ax

@@2: loop @@1

@@3: mov ax, bx

ret

EndP

 

End

Перед обращением к подпрограмме, написанной на языке Паскаль, в стек в соответствующем порядке следует поместить передаваемые параметры. В данном случае такой параметр один — число элементов массива.

Так как подпрограмма, написанная на языке Паскаль, не гарантирует сохранения регистров AX, BX, CX и DX, то в случае необходимости сохранения их значений следует перед обращением к подпрограмме, написанной на языке Паскаль, сохранить в стеке значения соответствующих регистров, а после возвращения из подпрограммы — восстановить их. В данном примере сохраняется содержимое регистра BX, в котором записано минимальное число.

При написании программ, содержащих отдельные части, написанные на языке ассемблера и Паскаль, следует обращать внимание на способ адресации (дальний — far или ближний — near). Здесь существует следующее правило: если подпрограмма объявляется в интерфейсной части какого-либо модуля, то она должна иметь дальнюю адресацию, в других случаях (подпрограмма объявляется в файле, содержащим основную программу, или в исполнительной части модуля) следует использовать ближнюю адресацию. Внешнюю подпрограмму нельзя объявлять внутри другой подпрограммы.

Использование встроенного ассемблера

Встроенный ассемблер обладает многими возможностями языка Turbo assembler, он приспособлен к использованию в подпрограммах, написанных на языке Паскаль (позволяет использовать идентификаторы программы, написанные на языке Паскаль, комментарии, имеющие такой же вид, как в языке Паскаль, позволяет воспользоваться встроенным отладчиком для пошагового выполнения программы, контроля содержимого регистров и параметров программы и т.д.).

Так же как и Turbo assembler, встроенный ассемблер предполагает использование ряда предопределенных стандартных идентификаторов, имеющих специальное назначение. Если в программе будет введен идентификатор с таким же именем, но имеющий другое назначение, в частях программы, написанных на встроенном ассемблере, будет отдано предпочтение стандартному назначению этого идентификатора.

Наряду с возможностью использования идентификаторов языка Паскаль, встроенный ассемблер использует три дополнительных идентификатора:

@Code — текущий кодовый сегмент (используется только с оператором SEG);

@Data — текущий сегмент данных (используется только с оператором SEG);

@Result — результат, полученный функцией (можно использовать только внутри функции).

При использовании встроенного ассемблера нельзя использовать:

— стандартные процедуры и функции;

— специальные массивы Mem, MemW, MemL, Port и PortW;

— константы типа string, вещественных типов и типа-множества;

— процедуры и функции, объявленные с директивой inline;

— метки, объявленные не в этом блоке.

Часть программы, написанная на языке ассемблера, помещается в операторные скобки asm . . . end.

Пример.

const

N = 7;

Massiv: array[1..N] of integer = (1, 2, 3, 2, 10, 7, 2);

 

function Max(var Mas; n:integer): integer;

begin

asm

lds si, Mas

xor ax,ax

mov bx, 8001h

mov cx, n

cmp cx, ax

jle @@3

@@1: lodsw

cmp ax, bx

jle @@2

mov bx,ax

@@2: loop @@1

@@3: mov @Result, bx

end;

end;

 

begin

Wtiteln(‘Максимальное число массива равно: ’, Max(Massiv, N));

end.

 

При использовании встроенного ассемблера комментарии пишутся таким же образом, как и в языке Паскаль. Назначение точки с запятой другое — этим знаком отделяются друг от друга команды, написанные на одной строке, например:

lds si, Mas; xor ax,ax; mov bx, 8001h

Использование директивы ASSEMBLER

Если ту или иную подпрограмму нужно полностью написать на языке ассемб­лера, используя встроенный ассемблер, можно вместо операторных скобок asm … end использовать директиву assembler, которая имеет ряд особенностей.

Во-первых, все передаваемые параметры, размером отличные от 1, 2 или 4 байт, передаются всегда своим адресом без создания копии в стеке.

Во-вторых, нельзя использовать для передачи результата функции перемен­ную @Result. Результат передается точно так же, как и при использовании TASM. Исключение составляет результат типа string. В этом случае в переменной @Result находится адрес строки, в которую следует поместить по­лученную информацию.

В-третьих, для процедур и функций, не имеющих формальных и локальных параметров, вообще не выделяется область стека.

В-четвертых, так же как и в предыдущем случае, автоматически оформляется начало и конец подпрограммы, связанные с сохранением регистра ВР и освобож­дением стека от передаваемых параметров.

Пример.

const

N = 7;

Massiv: array[1..N] of integer = (1, 2, 3, 2, 10, 7, 2);

function Max(var Mas; n:integer): integer; assembler;

asm

lds si, Mas

xor ax,ax

mov bx, 8001h

mov cx, ax

jle @@3

@@1: lodsw

cmp ax, bx

jle @@2

mov bx,ax

@@2: loop @@1

@@3: mov ax, bx

end;

 

begin

Wtiteln(‘Максимальное число массива равно: ’, Max(Massiv, N));

end.

Массивы Mem, MemW и MemL

В Turbo Pascal реализованы три предопределенных массива Mem, MemW и MemL. Эти массивы используются для прямого доступа к памяти. Каждый элемент массива Mem представляет собой байт, каждый элемент массива MemW — это слово, а каждый элемент массива MemL является значением двойного слова.

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

Mem[$0040:$$0049] := 7;

Data := MemW[Seg(v):Ofs(v)];

MemLond := MemL[64:3*4];

Первый оператор сохраняет значение 7 в байте $0040:$0049. Второй оператор помещает значение длиной в слово, записанное в первых двух байтах переменной V, в переменную Data. Третий оператор помещает значение длинного целого типа, записанное по адресу $0040:$000C, в переменную MemLong.



<== предыдущая лекция | следующая лекция ==>
Функция обработки ошибки динамически распределяемой области памяти | 


Карта сайта Карта сайта укр


Уроки php mysql Программирование

Онлайн система счисления Калькулятор онлайн обычный Инженерный калькулятор онлайн Замена русских букв на английские для вебмастеров Замена русских букв на английские

Аппаратное и программное обеспечение Графика и компьютерная сфера Интегрированная геоинформационная система Интернет Компьютер Комплектующие компьютера Лекции Методы и средства измерений неэлектрических величин Обслуживание компьютерных и периферийных устройств Операционные системы Параллельное программирование Проектирование электронных средств Периферийные устройства Полезные ресурсы для программистов Программы для программистов Статьи для программистов Cтруктура и организация данных


 


Не нашли то, что искали? Google вам в помощь!

 
 

© life-prog.ru При использовании материалов прямая ссылка на сайт обязательна.

Генерация страницы за: 4.216 сек.