Республики казахстан южно-казахстанский экономико-технологический



бет14/15
Дата15.06.2016
өлшемі2.05 Mb.
#137969
түріПрограмма обучения студентов
1   ...   7   8   9   10   11   12   13   14   15

Выражения


Встроенный ассемблер вычисляет все выражения, как 32-разрядные значения-указатели. Он не поддерживает значения с плавающей точкой и строковые значения, за исключением строковых констант.

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


Идентификаторы


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

@Code @Data @Result

Идентификаторы @Code и @Data представляют текущие сегменты кода и данных соответственно. Их следует использовать только в сочетании с операцией SEG:



asm

mov ax,SEG @Data

mov ds,ax

end;

Идентификатор @Result в операторной части функции переменную - результат функции. Например, в функции:



function Sum(X, Y: Integer): Integer;

begin

Sum := X + Y;

end;

в операторе, присваивающем результат функции переменной Sum, можно было бы при записи на встроенном ассемблере использовать переменную @Result:



function Sum(X, Y: Integer): Integer;

begin

asm

mov ax,X

add ax,Y

mov @Result,ax

end;

end;

В выражениях встроенного ассемблера нельзя использовать следующие идентификаторы:

- стандартные процедуры и функции (например, WriteLn, Chr);

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

- строки, значения с плавающей точкой и константы множественного

типа;


- метки, которые не описаны в текущем блоке;

- идентификатор @Result вне функции.

В Таблице 24.3 приведены значение, класс и тип различного вида идентификаторов, которые можно использовать в выражениях встроенного ассемблера (классы и типы выражений описываются в следующем разделе):

Значения, классы и типы идентификаторов Таблица 24.3

-------------T--------------------T----------------T-----------

¦Идентификат.¦ Значение ¦ Класс ¦ Тип ¦

+------------+--------------------+----------------+------------+

¦ Метка ¦ Адрес метки ¦ Память ¦ SHORT ¦

¦ Константа ¦ Значение константы ¦ Непосредствен- ¦ 0 ¦

¦ ¦ ¦ ный ¦ ¦

¦ Тип ¦ 0 ¦ Память ¦ Размер типа¦

¦ Поле ¦ Смещение поля ¦ Память ¦ Размер типа¦

¦ Переменная ¦ Адрес переменной ¦ Память ¦ Размер типа¦

¦ Процедура ¦ Адрес процедуры ¦ Память ¦ NEAR / FAR¦

¦ Функция ¦ Адрес функции ¦ Память ¦ NEAR / FAR¦

¦ Модуль ¦ 0 ¦ Непосредствен- ¦ 0 ¦

¦ ¦ ¦ ный ¦ ¦

¦ @Code ¦ Адрес сегмента кода¦ Память ¦ 0FFF0H ¦

¦ @Data ¦ Адрес сегмента ¦ Память ¦ 0FFF0H ¦

¦ ¦ данных ¦ ¦ ¦

¦ @Result ¦ Смещение перемен- ¦ Память ¦ Размер типа¦

¦ ¦ ной результата ¦ ¦ ¦

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

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

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

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



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

  • специальные массивы Mem, MemW, MemL, Port и PortW (см. п. 13);

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

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

  • метки, объявленные не в данном блоке.



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

Директива BYTE . Это директива резервирует байты ОЗУ (в области Data). Все директивы начинаются с символа «точка».

Пример №1:
.DSEQ

Var1: .BYTE 1

.CSEQ

ldi r30, low(varl)

ldi r31, high(varl)

ld r1, z
Директива .DSEQ . Определяет, что нижеследующие строки относятся к области Data ОЗУ. Эта директива не имеет операндов.

Директива .BYTE . Имеет один обязательный операнд, указывающий количество выделенных байтов.

Если необходимо чтобы обращение к выделенным байтам происходило по имени, то вводится метка (в данном случае это метка Var 1).



Директива .CSEQ. Указывает компилятору, что последующие строчки программы должны компилироваться и располагаться в области ПЗУ.

В последующих командах используется переменная Var 1, определяющая содержимое ячеек памяти ОЗУ.

Выражения low и high являются стандартными выражениями языка Assembler и предназначены для определения старшего и младшего байтов адреса переменной Var 1, указанного в качестве операнда этих выражений.

Пример №2:
Определить старший и младший байты числа 30010. Переводим 30010→Х16

300| 16



288| 18|16

12 16| 1|16

2 0| 0

1

30010→12C16



Старший байт – 01, младший байт – 2С.
Директива .DEF. Эта директива назначает регистру символическое имя. Это имя может использоваться в нижеследующей части программы для обращения к данному регистру. Символическое имя может быть переименовано в программе несколько раз. Синтаксис этой директивы следующий:
.DEF Символическое имя =регистр

Пример №3:

.DEF temp=R16

.DEF ior=R0

.CSEQ

.ldi _ temp, 0×f0

.eor temp, ior
Директива .DEVICE. Определяет устройство, для которого компилируется программа. Использование данной директивы позволяет компилятору выдать предупреждение, если появится команда, не поддерживаемая данным контроллером.

Пример №4:
.DEVICE AT90S2313
Директива .EQU. Позволяет определить константу путем задания ее меткой. Формат этой директивы:
.EQU метка=выражение

Пример №5:

.EQU io_offset=0×23

.EQU port a = io_offset+2

.CSEQ

clr r2

out port a, r2
Директива .include. Означает вложение другого файла (содержимое файла включается в программу при компиляции).

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



Пример №6:
; файл iodefs.asm

.EQU sreq=0×3F

.EQU sphigh=0×3e

.EQU splow=0×3d

; файл incdemo.asm

.include iodefs.asm

in ro,sreg
Директива .ORG устанавливает счетчик в положение равным заданной величине, которая входит как параметр в эту директиву. Для сегмента данных она устанавливает счетчик положения ОЗУ, для сегмента программ или памяти программ она устанавливает содержимое РС (программного счетчика), а для сегмента Eeprom устанавливает положение в области Eeprom.

Если директиве предшествует метка, то она становится равной адресу, указанному в параметре директивы при компиляции программы.

Перед началом компиляции РС и счетчик Eeprom нулю, а счетчик ОЗУ=32.

Для ОЗУ и Eeprom используются побайтные счетчики, а для программного сегмента пословные.


Пример №7:
.DSEQ

.ORG 0×37

; variable: .BYTE 1

; резервирует байт по адресу 0×37

.CSEQ

.ORG 0×10

MOV RO, R1; данная команда размещается по адресу 0×10
Директива .SET присваивает метке определенное значение, которое далее может быть использовано в выражениях. В отличие от директивы EQU значение метки может быть изменено другой директивой .SET

Пример №8:
.SET io1=0×23

.SET PORTA=io1+1

.CSEQ

out PORTA, R2
Модели памяти. Директивы определения моделей памяти.
Директива DOSSEG

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


Директива DOSSEG приводит к тому, что сегменты в программе

Ассемблера будут сгруппированы в соответствии с соглашениями по

упорядочиванию сегментов фирмы Microsoft. В данным момент вам не

следует вникать в смысл того, что это означает. Запомните просто,

что почти все автономные программы на Ассемблере будут прекрасно

работать, если вы начнете их с директивы DOSSEG.

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

уровня задавать директиву DOSSEG не обязательно, так как в языке

высокого уровня автоматически выбирается упорядочивание сегментов

по стандарту фирмы Microsoft.

Однако эта директива не повредит. Из всего перечисленного можно сделать заключение, что использование директивы DOSSEG в качестве первой строки вашей программы является простейшим подходом (если у вас нет конкретной причины поступать иначе). Благодаря этому вы сможете использовать определенный порядок сегментов.
Директива .MODEL

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

Директива .MODEL определяет модель памяти в модуле Ассемблера, где используются упрощенные директивы определения сегментов.

В "ближнем" коде переходы осуществляются с помощью загрузки одного регистра IP, а в "дальнем" коде - путем загрузки регистров CS и IP. Аналогично, к "ближним" данным обращение выполняется только по смещению, а к "дальним" - с помощью полного адреса "сегмент:смещение". Термин "дальний" (FAR) означает использование полного 32-разрядного адреса ("сегмент:смещение"), а "ближний" (NEAR) означает использование 16-разрядных смещений.


Существуют следующие модели памяти:


  1. Сверхмалая

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




  1. Малая

Код программы должен размещаться внутри одного сегмента данных размером 64К, а данные программы должны размещаться в отдельном сегмента данных (размером 64К). И код, и данные должны быть ближнего типа.




  1. Средняя

Код программы может превышать 64К, но данные программы должны помещаться в один сегмент размером 64К. Код имеет дальний тип, а данные - ближний.




  1. Компактная

Код программы должен помещаться в один сегмент размером 64К, а данные могут превышать по размеру 64К. Код имеет ближний тип, а данные – дальнего типа.




  1. Большая

И код, и данные программы могут превышать 64К, но один массив данных не может превышать 64К. И код, и данные имеют дальний тип.




  1. Сверхбольшая

И код, и данные программы могут превышать по размеру 64К. Массивы данных также могут превышать 64К. Код и данные имеют дальний тип. Указатели на элементы массива также дальнего типа. Заметим, что с точки зрения Ассемблера большая и сверхбольшая модели идентичны. Сверхбольшая модель не поддерживает автоматически массивы данных, превышающие 64К.

Немногие программы на Ассемблере используют более 64К кода

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

Описанные здесь модели памяти соответствуют моделям, используемым в Турбо Си (и во многих других компиляторах для компьютера IBM PC). Когда вы компонуете модуль на Ассемблере с языком высокого уровня, убедитесь, что используется правильная директива .MODEL. Эта директива обеспечивает соответствие имен сегментов Ассемблера тем именам, которые используются в языках высокого уровня, а также используемого по умолчанию типа меток PROC, использующихся для наименования подпрограмм, процедур и функций, типу (ближнему или дальнему), используемому в языках высокого уровня.

Директиву .MODEL необходимо указывать, если вы используете упрощенные директивы определения сегментов, так как в противном случае Турбо Ассемблер не будет знать как устанавливать сегменты, определенные с помощью директив .CODE и .DATA. Директива .MODEL должна предшествовать директивам .CODE, .DATA и .STACK.

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

.MODEL small

.STACK 200h

.DATA


MemVar DW

.

.



.

.CODE


ProgramStart:

Mov ax, @data

Mov ds, ax

Mov ax, [MemVar]

.

.

.



Mov ah, 4ch

Int 21h


END

ProgramStart


Другие упрощенные директивы определения сегментов

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


Имеется еще несколько общеупотребительных директив определения сегментов. Вам они потребуются только для больших или специальных программ, поэтому мы только кратко упомянем их.

Директива .DATA? используется аналогично директиве .DATA, но она определяет ту часть сегмента данных, которая содержит неинициализированные данные. Она обычно используется в модулях Ассемблера, которые компонуются с языком высокого уровня.


Директива .FARDATA позволяет вам определить дальний сегмент данных, то есть сегмент данных, отличный от стандартного сегмента @data, разделяемого (совместно используемого) всеми модулями. Директива .FARDATA позволяет в модуле Ассемблера определить свои собственные сегменты размером до 64К. Если задана директива .FARDATA, то именем определенного по этой директиве дальнего сегмента данных будет @fardata, так же как @data - имя сегмента, определенного по директиве .DATA.
Директива .FARDATA? во многом аналогична директиве .FARDATA, но она определяет неинициализированный сегмент дальнего типа. Так же как и для директивы .FARDATA и имени @fardata, при указании директивы .FARDATA? сегмент данных дальнего типа, определенный по этой директиве, получает имя @fardata?.
Директива .CONST определяет ту часть сегмента данных, в которой содержатся константы. Опять-таки это имеет силу только при компоновке кода Ассемблера с языком высокого уровня.
При использовании упрощенных директив определения сегментов можно использовать некоторые предопределенные метки.

Метка @FileName представляет собой имя ассемблируемого файла, @curseg - имя сегмента, в который Турбо Ассемблер в данный момент выполняет ассемблирование, @CodeSize - это 0 для моделей памяти с ближними сегментами кода (сверхмалой, малой и компактная), 1 - для компактной и большой модели памяти и 2 - для сверхбольшой модели.

Аналогично, @DataSize = 0 в модели памяти с сегментами данных ближнего типа (сверхмалая, малая и средняя модель памяти), 1 в компактной и большой моделях и 2 - для сверхбольшой модели.



Достарыңызбен бөлісу:
1   ...   7   8   9   10   11   12   13   14   15




©dereksiz.org 2024
әкімшілігінің қараңыз

    Басты бет