Описание простых типов данных асемблера




 

Рассмотрим описание данных в программе на ассемблере. Любая программа предназначена для обработки некоторой информации, поэтому вопрос о том, как описать данные с использованием средств языка, обычно встает одним из первых. TASM предоставляет очень широкий набор средств описания и обработки данных, который вполне сравним с аналогичными средствами некоторых языков высокого уровня.

Начнем обсуждение с правил описания простых типов данных, которые являются базовыми для описания более сложных типов. Для описания простых типов данных в программе используются специальные директивы резервирования и инициализации данных, которые по сути являются указаниями транслятору на выделение определенного объема памяти. Если проводить аналогию с языками высокого уровня, то директивы резервирования и инициализации данных являются определениями переменных. Машинного эквивалента этим директивам нет; просто транслятор, обрабатывая каждую такую директиву, выделяет необходимое количество байт памяти и при необходимости инициализирует эту область некоторым значением. Директивы резервирования и инициализации данных простых типов имеют формат, показанный на рис. 5.17.

 

На рис. 5.17 использованы следующие обозначения.

 

§? показывает, что содержимое поля не определено, то есть при задании директивы с таким значением выражения содержимое выделенного участка физической памяти изменяться не будет. Фактически создается неинициализированная переменная;

 

§ значение инициализации — значение элемента данных, которое будет занесено в память после загрузки программы. Фактически создается инициализированная переменная, в качестве которой могут выступать константы, строки символов, константные и адресные выражения в зависимости от типа данных. Подробная информация приведена в приложении;

 

§ выражение — итеративная конструкция с синтаксисом, описанным на рис. 5.17. Эта конструкция позволяет повторить последовательное занесение в физическую память выражения в скобках п раз.

 

§ имя — некоторое символическое имя метки или ячейки памяти в сегменте данных, используемое в программе.

Рис. 5.17. Директивы описания данных простых типов

На рис. 5.17 представлены следующие поддерживаемые TASM директивы ре-зервирования и инициализации данных:

§ db — резервирование памяти для данных размером 1 байт;

§ dw — резервирование памяти для данных размером 2 байта;

§ dd — резервирование памяти для данных размером 4 байта;

§ df — резервирование памяти для данных размером 6 байт;

§ dp — резервирование памяти для данных размером 6 байт;

§ dq — резервирование памяти для данных размером 8 байт;

§ dt — резервирование памяти для данных размером 10 байт.

 

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

 

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

 

 

Посмотрим, как выглядит сегмент данных программы листинга 5.2 в памяти компьютера. Это даст нам возможность обсудить практическую реализацию обозначенного нами принципа размещения данных. Для этого запустим отладчик TD. EXE, входящий в комплект поставки TASM. Опишем этот процесс по шагам.

Введем код из листинга 5.2 в файл с названием prg_5_2.asm. Как мы договорились раньше, все манипуляции с файлом будем производить в директории work, где уже содержатся все необходимые для компиляции, компоновки и отладки файлы пакета TASM.

Запустим процесс трансляции файла следующей командой:

tasm.exe /zi prg_5_2.asm,,,

После устранения синтаксических ошибок запустим процесс компоновки объектного файла:

tlink.exe /v prg_5_2.obj

Теперь можно производить отладку:

td prg_5_2.exe

Если все было сделано правильно, то в отладчике откроется окно Module с исходным текстом программы. Для того чтобы с помощью отладчика просмотреть область памяти, содержащую наш сегмент данных, необходимо открыть окно Dump. Это делается с помощью команды главного меню View| Dump.

Но одного открытия окна недостаточно; нужно еще настроить его на адрес начала сегмента данных. Этот адрес должен содержаться в сегментном регистре ds, но, как сказано выше, перед началом выполнения программы адрес в ds не соответствует началу сегмента данных. Нужно перед первым обращением к любому символическому имени произвести загрузку действительного физического адреса сегмента данных. Обычно это действие не откладывают в долгий ящик и производят первыми двумя командами в сегменте кода. Действительный физический адрес сегмента данных извлекают как значение предопределенной переменной @data. В нашей программе эти действия выполняют команды

 

mov ах,@data

mov ds,ах

Для того чтобы посмотреть содержимое нашего сегмента данных, нужно остановить выполнение программы после этих двух команд. Это можно сделать, если перевести отладчик в пошаговый режим с помощью клавиш F7 или F8. Нажмите два раза F8. Теперь можно открыть окно Dump.

 

В окне Dump вызовите контекстное меню, щелкнув правой кнопкой мыши. В появившемся контекстном меню выберите команду Goto. Появится диалоговое окно, в котором нужно ввести начальный адрес памяти, начиная с которого будет выводиться информация в окне Dump. Синтаксис задания этого адреса должен соответствовать синтаксису задания адресного операнда в программе на ассемблере (см. начало этого урока). Мы бы хотели увидеть содержимое памяти для нашего сегмента данных, начиная с его начала, поэтому введем ds: 0000. Для удобства, если сегмент достаточно велик, это окно можно распахнуть на весь экран. Для этого нужно щелкнуть на символе в правом верхнем углу окна Dump. Вид экрана показан на рис. 5.18.

Обсудим рис. 5.18. На нем можно видеть данные нашего сегмента в двух представлениях: шестнадцатеричном и символьном. Видно, что со смещением 0000 расположены символы, входящие в строку message. Она занимает 34 байта. После нее следует байт, имеющий в сегменте данных символическое имя perem_1, содержимое этого байта 0ffh. Теперь обратите внимание на то, как размещены в памяти байты, входящие в слово, обозначенное символическим именем реrem_2.

Сначала следует байт со значением 7fh, а затем со значением 3ah. Как видите, в памяти действительно сначала расположен младший байт значения, а затем старший. Теперь посмотрим и самостоятельно проанализируем размещение байтов для поля, обозначенного символическим именем perem_3. Оставшуюся часть сегмента данных можем теперь проанализировать самостоятельно. Остановимся лишь на двух специфических особенностях использования директив резервирования и инициализации памяти. Речь идет о случае использования в поле операндов директив dw и dd символического имени из поля имя этой или другой директивы резервирования и инициализации памяти. В нашем примере сегмента данных это директивы с именами adr и adr_full. Когда транслятор встречает директивы описания памяти с подобными операндами, то он формирует в памяти значения адресов тех переменных, чьи имена были указаны в качестве операндов. В зависимости от директивы, применяемой для получения такого адреса, формируется либо полный адрес (директива dd) в виде двух байтов сегментного адреса и двух байтов смещения, либо только смещение (директива dw). Найдите в дампе на рис. 5.18 поля, соответствующие именам adr и adr_full, и проанализируйте их содержимое.

Puc. 5.18. Окно дампа памяти

 

 

Любой переменной, объявленной с помощью директив описания простых типов данных, ассемблер присваивает три атрибута:

1. Сегмент (seg) — адрес начала сегмента, содержащего переменную.

2. Смещение (offset) в байтах от начала сегмента с переменной.

3. Тип (type) — определяет количество памяти, выделяемой переменной в соответствии с директивой объявления переменной.

 

Получить и использовать значение этих атрибутов в программе можно с помощью рассмотренных нами выше операторов ассемблера seg, offset и type.

 

Подведем некоторые итоги:

 

 

ü Программа на ассемблере, отражая особенности архитектуры микропроцессора, состоит из сегментов — блоков памяти, допускающих независимую адресацию.

ü Каждый сегмент может состоять из предложений языка ассемблера четырех типов: команд ассемблера, макрокоманд, директив ассемблера и строк комментариев.

ü Ассемблер допускает большое разнообразие типов операндов, которые могут содержаться непосредственно в команде, в регистрах и в памяти.

ü Операнды в команде могут быть выражениями.

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

ü Упрощенные директивы сегментации позволяют унифицировать интерфейс с языками высокого уровня и облегчают разработку программ, повышая наглядность кода.

ü Существует два режима работы TASM: MASM и IDEAL. Назначение режима MASM — обеспечить полную совместимость с транслятором MASM фирмы Microsoft. Назначение режима IDEAL — упростить синтаксис конструкций языка, повысить эффективность и скорость работы транслятора.

ü TASM поддерживает разнообразные типы данных, которые делятся на простые (базовые) и сложные. Простые типы служат как бы «кирпичиками» для построения сложных типов данных.

ü Директивы описания простых типов данных позволяют зарезервировать и при необходимости инициализировать области памяти заданной длины.

ü Каждой переменной, объявленной с помощью директивы описания данных, TASM назначает атрибуты, доступ к которым можно получить с помощью соответствующих операторов ассемблера.

 



Поделиться:




Поиск по сайту

©2015-2024 poisk-ru.ru
Все права принадлежать их авторам. Данный сайт не претендует на авторства, а предоставляет бесплатное использование.
Дата создания страницы: 2017-08-27 Нарушение авторских прав и Нарушение персональных данных


Поиск по сайту: