- •«Национальный исследовательский ядерный университет «мифи»
- •Озерский технологический институт-филиал нияу мифи
- •Кафедра: Электроники и автоматики
- •Лабораторная работа №2
- •Структура программы на ассемблере. Представление простых типов данных.
- •Теоретические сведения
- •Порядок выполнения лабораторной работы
- •Контрольные вопросы
Министерство образования и науки российской федерации федеральное государственное автономное образовательное учреждение высшего профессионального образования
«Национальный исследовательский ядерный университет «мифи»
Озерский технологический институт-филиал нияу мифи
Кафедра: Электроники и автоматики
Лабораторная работа №2
по дисциплине «ПО ИП»
Преподаватель |
|
|
|
|
Изарова Е.Г. |
Выполнил студент группы |
1ИТ-30 |
|
|
|
Новиков А.С. |
|
(индекс группы) |
|
(дата, подпись) |
|
(Ф.И.О.)
|
2012
Структура программы на ассемблере. Представление простых типов данных.
Цель работы:
Изучить директивы описания данных простых типов; с помощью окна Dump отладчика tdebug.exe просмотреть область памяти, содержащую сегмент данных программы.
Теоретические сведения
Для описания простых типов данных в программе используются специальные директивы резервирования и инициализации данных, которые по сути являются указаниями транслятору на выделение определенного объема памяти. Если проводить аналогию с языками высокого уровня, то директивы резервирования и инициализации данных являются определениями переменных. Машинного эквивалента этим директивам нет; просто транслятор, обрабатывая каждую такую директиву, выделяет необходимое количество байт памяти и при необходимости инициализирует эту область некоторым значением. Директивы резервирования и инициализации данных простых типов имеют формат, показанный на рисунке.
Рисунок 1. Директивы описания данных простых типов.
? – показывает, что содержимое поля не определено, т.е. при задании директивы с таким значением выражения содержимое выделенного участка физической памяти изменяться не будет. Фактически создается неинициализированная переменная;
значение инициализации – значение элемента данных, которое будет занесено в память после загрузки программы. Фактически создается инициализированная переменная, в качестве которой могут выступать константы, строки символов, константные и адресные выражения в зависимости от типа данных;
выражение – итеративная конструкция с синтаксисом, описанным на рис.1 эта конструкция позволяет повторить последовательное занесение в физическую память выражения в скобках n раз;
имя – некоторое символическое имя метки или ячейки памяти в сегменте данных, используемое в программе.
На рис.1. представлены следующие поддерживаемые TASM директивы резервирования и инициализации данных:
db – резервирование памяти для данных размером 1 байт;
dw – резервирование памяти для данных размером 2 байт;
dd – резервирование памяти для данных размером 4 байт;
df – резервирование памяти для данных размером 6 байт;
dp – резервирование памяти для данных размером 6 байт;
dq – резервирование памяти для данных размером 8 байт;
dt – резервирование памяти для данных размером 10 байт для ДКД-чисел (BCD).
Очень важно запомнить порядок размещения данных в памяти. Он напрямую связан с логикой работы микропроцессора с данными. Микропроцессоры Intel требуют следования данных в памяти по принципу: младший байт по младшему адресу.
Листинг 1. Пример текста программы Prg_5_2.asm на языке ассемблера, с использованием директив резервирования и инициализации данных.
;---------Prg_5_2.asm---------------------------------------
; Пример использования директив резервирования и инициализации данных.
;-----------------------------------------------------------
masm
model small
.stack 100h
.data
message db 'Запустите эту программу в отладчике','$'
perem_1 db 0ffh
perem_2 dw 3a7fh
perem_3 dd 0f54d567ah
mas db 10 dup (' ')
pole_1 db 5 dup (?)
adr dw perem_3
adr_full dd perem_3
fin db 'Конец сегмента данных программы $'
.code
start:
mov ax,@data
mov ds,ax
mov ah,09h
mov dx,offset message
int 21h
mov ax,4c00h
int 21h
end start
Для того, чтобы посмотреть содержимое сегмента данных программы Prg_5_2.asm нужно создать исполняемый модуль prg_5_2.ехе с помощью командных строк:
tasm.exe /zi prg_5_2,,,
tlink.exe /v prg_5_2.obj.
Теперь можно производить отладку: td prg_5_2.exe.
Если все было сделано правильно, то в отладчике откроется окно Module с исходным текстом программы. Для того чтобы с помощью отладчика просмотреть область памяти, содержащую наш сегмент данных, необходимо открыть окно Dump. Это делается с помощью команды главного меню ViewDump.
Но одного открытия окна недостаточно: нужно еще настроить его на адрес начала сегмента данных. Этот адрес должен содержаться в сегментном регистре ds, но, как сказано выше, перед началом выполнения программы адрес в ds не соответствует началу сегмента данных. Нужно перед первым обращением к любому символическому имени произвести загрузку действительного физического адреса сегмента данных. Это действие производят двумя командами в сегменте кода. Действительный физический адрес сегмента данных извлекают как значение предопределенной переменной @data. В нашей программе эти действия выполняют команды:
mov ax, @data
mov ds, ax
Для того чтобы посмотреть содержимое нашего сегмента данных, нужно остановить выполнение программы после этих двух команд. Это можно сделать, если перевести отладчик в пошаговый режим с помощью клавиш F7 или F8. Нажмите два раза F8. Теперь можно открыть окно Dump.
В окне Dump вызовите контекстное меню, щелкнув правой кнопкой мыши. В появившемся контекстном меню выберите команду Goto. Появится диалоговое окно, в котором нужно ввести начальный адрес памяти ds:0000, начиная с которого будет выводиться информация в окне Dump.
Рассмотрим рисунок 2. На нем вы видите данные Вашего сегмента в двух представлениях: шестнадцатеричном и символьном. Видно, что со смещением 0000 расположены символы, входящие в строку message. Она занимает 34 байта. После нее следует байт, имеющий в сегменте данных символическое имя perem_1, содержимое этого байта 0ffh. (Если шестнадцатеричное число начинается с латинской буквы, то перед ней ставится нуль. Это необходимо транслятору для того, чтобы можно было отличить текст от чисел.) Теперь обратите внимание на то, как размещены в памяти байты, входящие в слово, обозначенное символическим именем perem_2. Сначала следует байт со значением 7fh, а затем со значением 3ah. Как видите, в памяти действительно сначала расположен младший байт значения, а затем старший.
Теперь посмотрите и самостоятельно проанализируйте размещение байтов для поля, обозначенного символическим именем perem_3. Оставшуюся часть сегмента данных вы можете теперь проанализировать самостоятельно.
Остановимся лишь на двух специфических особенностях использования директив резервирования и инициализации памяти. Речь идет о случае использования в поле операндов директив dw и dd символического имени из поля имя этой или другой директивы резервирования и инициализации памяти. В нашем примере сегмента данных это директивы с именами adr и adr_full. Когда транслятор встречает директивы описания памяти с подобными операндами, то он формирует в памяти значения адресов тех переменных, чьи имена были указаны в качестве операндов. В зависимости от директивы, применяемой для получения такого адреса, формируется либо полный адрес (директива dd) в виде двух байтов сегментного адреса и двух байтов смещения, либо только смещение (директива dw).
Найдите в дампе на рисунке 2 поля, соответствующие именам adr и adr_full и проанализируйте их содержимое.
Dump
ds: 0000 87 A0 AF E3 E1 E2 A8 E2 Запустит
ds: 0008 A5 20 ED E2 E3 20 AF E0 е эту пр
ds: 0010 AE A3 E0 A0 AC AC E3 20 ограмму
ds: 0018 A2 20 AE E2 AB AO A4 E7 в отладч
ds: 0020 A8 AA A5 24 FF 7F 3A 7A ике$ :z
ds: 0028 56 4D F5 20 20 20 20 20 VMI
ds: 0030 20 20 20 20 20 00 00 00
ds: 0038 00 00 27 00 27 00 42 1B ‘ ‘ B
ds: 0040 8A AE AD A5 E6 20 E1 A5 Конец се
ds: 0048 A3 AC A5 AD E2 A0 20 A4 гмента д
ds: 0050 A0 AD AD EB E5 20 AF E0 анных пр
Рисунок 2. Окно дампа памяти.
Любой переменной, объявленной с помощью директив описания простых типов данных, ассемблер присваивает три атрибута:
Сегмент (seg) – адрес начала сегмента, содержащего переменную.
Смещение (offset) в байтах от начала сегмента с переменной.
Тип (type) – определяет количество памяти, выделяемой переменной в соответствии с директивой объявления переменной.
Получить и использовать значение этих атрибутов в программе можно с помощью рассмотренных операторов ассемблера seg, offset, и type.