assembler. Учебник для вузов_Юров В.И_2003 -637с (862834), страница 26
Текст из файла (страница 26)
Директивой ОТможно задавать следующие значения:Р выражение или константу, принимающую значение из диапазона-32 768...+32 767 (для чисел со знаком и процессора i8086), 0...65 535 (длячисел без знака и процессора 18086), -2 147 483 64S...+2 147 483 647 (длячисел со знаком и процессора 1386 и выше) или 0...4 294 967 295 (для чиселбез знака и процессора 1386 и выше);Р относительное или адресное выражение, состоящее из 32 или менее битов(для i80386) или 16 или менее битов (для первых моделей);Р адресное выражение, состоящее из 16-разрядного сегмента и 32-разрядногосмещения;Р константу со знаком из диапазона -279...279 - 1;80Р константу без знака из диапазона 0...2 - 1;Р строку длиной до 10 байтов, заключенную в кавычки;Р упакованную десятичную константу в диапазоне 0...99 999 999 999 999 999 999.116Глава 5.
Синтаксис ассемблераЗаметим, что все директивы позволяют задавать строковые значения, но нужно помнить, что в памяти эти значения могут выглядеть совсем не так, как онибыли описаны в директиве. Причиной этому является упоминавшийся ранее принцип «младший байт по младшему адресу». Для определения строк лучше использовать директиву DB. Задаваемые таким образом строки должны заключаться в кавычки. Эти кавычки могут быть одинарными ('') или двойными (""). Если задатьв строке подряд два таких ограничителя, то вторая кавычка (одинарная или двойная) будет частью строки.Для иллюстрации принципа «младший байт по младшему адресу» рассмотримлистинг 5.3, в котором определим сегмент данных.
В этом сегменте данных приведено несколько директив описания простых типов данных.Листинг 5.3. Пример использования директив резервированияи инициализации данныхmasmmodel small.stack 100h.datamessage db "Запустите эту программу в о т л а д ч и к е " , ' $ 'perem_l db Offhperem_2 dw 3a7fhperem_3 dd 0f54d567ahmasdb 10 dup (" ")pole_l db 5 dup (?)adrdw perem_3adr_fuUdd perem_3findb "Конец сегмента данных программы $".codestart:mov ax,@datamov d s . a xmov ah,09hmov d x . o f f s e t messageint21hmov ax,4c00hint 21hendstartВНИМАНИЕЕсли при дальнейшем изложении вам что-то будет непонятно, можно порекомендовать на время прерваться и вновь вернуться к этому материалупосле изучения главы 6.Итак, наша цель — посмотреть, как выглядит в памяти компьютера сегмент данных программы, представленной в листинге 5.3.
Это даст нам возможность обсудитьпрактическую реализацию обозначенного нами принципа размещения данных.1. Запустите отладчик td.exe, входящий в комплект поставки транслятора TASM.2. Введите код, представленный в листинге 5.3, и сохраните его в виде файла с названием prg_5_3.asm. Все манипуляции с файлом будем производить в каталогеwork, где должны содержаться все необходимые для компиляции, компоновкии отладки файлы пакета TASM.3.
Запустите процесс трансляции файла следующей командой:tasm.exe /zi prg_5_2.asm , , ,Простые типы данных ассемблера4.117После устранения синтаксических ошибок запустите процесс компоновки объектного файла:tlink.exe /v prg_5_2.obj5. Теперь можно производить отладку:td prg_5_2.exeЕсли все было сделано правильно, то в отладчике откроется окно Module с исходным текстом программы. Для того чтобы с помощью отладчика просмотретьобласть памяти, содержащую наш сегмент данных, необходимо открыть окно Dump.Это делается с помощью команды View > Dump главного меню.Но одного открытия окна недостаточно, нужно еще настроить его на адрес начала сегмента данных.
Этот адрес должен содержаться в сегментном регистре DS,но перед началом выполнения программы адрес в DS не соответствует началу сегмента данных. Нужно перед первым обращением к любому символическому имени произвести загрузку действительного физического адреса сегмента данных.Обычно это действие не откладывают и производят первыми двумя командамив сегменте кода. Действительный физический адрес сегмента данных извлекаюткак значение предопределенной переменной @data. В нашей программе эти действия выполняют командыmov a x , @ d a t amov d s , a xДля того чтобы посмотреть содержимое нашего сегмента данных, нужно остановить выполнение программы после этих двух команд.
Это можно сделать, еслиперевести отладчик в пошаговый режим с помощью клавиши F7 или F8. Нажмитедва раза клавишу F8. Теперь можно открыть окно Dump.В окне Dump вызовите контекстное меню, щелкнув правой кнопкой мыши, и выберите команду Goto. Появится диалоговое окно, в котором нужно ввести начальный адрес памяти, начиная с которого информация будет выводиться в окне Dump.Синтаксис задания этого адреса должен соответствовать синтаксису задания адресного операнда в программе на ассемблере. Если нужно увидеть содержимоепамяти для сегмента данных, начиная с начала, введите ds:0000 (рис.
5.20). Дляудобства, если сегмент довольно велик, это окно можно развернуть на весь экран.Для этого нужно щелкнуть на значке в виде стрелки (Т) в правом верхнем углуокна Dump.На рисунке представлено содержание сегмента данных программы из листинга 5.3 в двух представлениях: шестнадцатеричном и символьном. Видно, что со смещением 0000 расположены символы, входящие в строку message. Она занимает34 байта.
После нее следует байт, имеющий в сегменте данных символическое имяperem_l, содержимое этого байта — offh. Теперь обратите внимание на то, как размещены в памяти байты, входящие в слово, обозначенное символическим именемperem_2. Сначала следует байт со значением 7fh, а затем — со значением 3ah. Каквидим, в памяти действительно сначала расположен младший байт значения, а затем старший. Теперь проанализируйте порядок размещения байтов для поля, обозначенного символическим именем perem_3. Оставшаяся часть сегмента данныхне представляет трудности для самостоятельного анализа.
Есть смысл остановитьсялишь на двух специфических особенностях использования директив резервиро-118Глава 5. Синтаксис ассемблерал\1ji.y_.datamessage db 'Запустите эту программу в отладчикеpecem 1 db OffhресеиГз dd Of54d567ahmasdb 10 dup (' ')pole 1 db 5 dup (?)adcdw pecem 3adc full dd pecem 3fin db 'Конец сегмента.codestact:•mov•mov^mov•ax,6datads , axah,09hds:0000ds 0008ds 0010ds 0018ds 0020ds 0028ds 0030ds 0038ds 0040ds 0048ds 005087ASAEА2А85620008АA3АОАО2UA320AFEDEOAEАА AS4D F520 2000 27АЕ ADАС ASAD ADТI'?'E3E2АОE224ElE3ACABFF20 2020 2000 27AS E6AD E2EB E5E220ACАО7F20000020АО20A8AFE3А4ЗА200042El20AFE2EU20E77A2000IBASA4EOЗапуститe эту программув отладчике§ D:zVM1' ' В«Конец сегмента дэнных прпиint2 Inmovax,4cOOhint 2 Inend stact~Йв1р§ВПуск|-В$ф£', -4*$Й-,Уч '"Йвсе' •'.
Pant-3&ЭХ*-----WeадеШВтР-Step-teu~Кшт844Рис. 5.20. Окно дампа памятивания и инициализации памяти. Речь идет об указании в поле операндов директивDW и DD идентификатора из поля имени этой или другой директивы резервирования и инициализации памяти. В нашем примере сегмента данных это директивыс идентификаторами adr и adr_full. Когда транслятор встречает директивы описания памяти с подобными операндами, то он формирует в памяти значения адресовтех переменных, чьи идентификаторы указаны в качестве операндов. В зависимости от директивы, применяемой для получения такого адреса, формируется либополный адрес (директива DD) в виде двух байтов сегментного адреса и двух байтовсмещения, либо только смещение (директива dw).
Для тренировки найдите в представленном дампе поля, соответствующие идентификаторам adr и adr_full, и проанализируйте их содержимое.Любой переменной, объявленной с помощью директив описания простых типов данных, ассемблер присваивает три атрибута:« сегмент (seg) — адрес начала сегмента, содержащего переменную;>i смещение (offset) в байтах от начала сегмента с переменной;« тип (type) — объем памяти, выделяемой переменной в соответствии с директивой объявления переменной.Получить и использовать значение этих атрибутов в программе можно с помощью операторов ассемблера SEG, OFFSET и TYPE.Итоги119В заключение отметим, что в языке ассемблера существуют средства для описания сложных типов данных, основой которых являются описанные в этой главепростые типы данных.
Подробному обсуждению сложных типов данных посвящена глава 13.ИтогиПрограмма на ассемблере, отражая особенности архитектуры процессора, состоит из сегментов — блоков памяти, допускающих независимую адресацию.Каждый сегмент может состоять из предложений языка ассемблера четырехтипов: команд ассемблера, макрокоманд, директив ассемблера и строк комментариев.Ш Формальное описание синтаксиса языков программирования, в том числе ассемблера, удобно выполнять с использованием таких метасинтаксических языков, как синтаксические диаграммы и нормальные формы Бэкуса-Наура. Синтаксические диаграммы более наглядны, а расширенные формы Бэкуса-Наураболее компактны.^ Предложения ассемблера формируются из лексем, представляющих собой синтаксически неразделимые последовательности допустимых символов языка,имеющие смысл для транслятора.§i Ассемблер допускает большое разнообразие типов операндов, которые могутзадаваться неявно или содержаться непосредственно в команде, в регистрахи в памяти.
В двухоперандной машинной команде возможны следующие сочетания операндов:П регистр — регистр;D регистр — память;D память — регистр;D непосредственный операнд — регистр;П непосредственный операнд — память.И Операндами в команде могут быть числа, регистры, ячейки памяти, символьные идентификаторы. При необходимости операнд может быть задан выражением.1Ассемблер позволяет организовать гибкую прямую и косвенную адресацию операндов в памяти.Исходный текст программы разбивается на сегменты с помощью директив сегментации, которые делятся на стандартные и упрощенные.з Упрощенные директивы сегментации позволяют унифицировать интерфейсс языками высокого уровня и облегчают разработку программ, повышая наглядность кода.1> Транслятор TASM поддерживает разнообразные типы данных, которые делятся на простые (базовые) и сложные. Простые типы служат основой для построения сложных типов данных.120Глава 5.