$$$003-001-000$3.3.1 Практическое занятие №1
&&&
$$$003-001-001$3.3.1.1 Методические указания к практическому занятию №1
Данная лабораторная работа служит для ознакомления студентов с архитектурой процессоров семейства х86, получения начальных знаний об организации памяти ЭВМ в системе MS-DOS, а также для освоения принципов работы с языком ассемблера для Интел-совместимых процессоров.
Архитектура процессора Intel.
Микропроцессор, иначе называемый CPU(CentralProcessUnit), для программиста представляет собой набор 16-тиразрядных (т.е. имеющих объем 16 бит или 2 байта) регистров – особых ячеек памяти, интегрированных в микросхему процессора. Обращение к регистрам осуществляется значительно быстрее, чем к ячейкам внешней памяти. Каждый регистр имеет свое, отличное от других предназначение. Тем не менее, их можно разделить на 3 функциональных группы:
Общего назначения (РОН):
AX(Accumulator) – аккумулятор. Большинство арифметических действий производится с его помощью.
BX(Base) – регистр, использующийся для адресации данных внутри сегмента (см. ниже).
CX(Counter) – счетчик. Используется для организации циклов.
DX (Data) – регистр дополнительных данных. Иногда используется как дополнение аккумулятора.
Все регистры общего назначения могут рассматриваться как 16-битные (AX, BX,CX,DX), так и как 8-битные (AHиAL,BHиBL,CHиCL,DHиDLсоответственно). Причем идентификатором «AH» обозначается старший байт регистраAX, а «AL» - младший байт. Аналогичное правило верно и для остальных РОН.
Сегментные регистры:
CS(CodeSegment) – регистр сегмента кода. Содержит адрес начала этого сегмента.
DS(DataSegment) – регистр сегмента данных.
SS(StackSegment) – регистр сегмента стека.
ES(ExtraSegment) – регистр дополнительного сегмента.
Понятие сегмента описано в пункте «Организация памяти».
Индексные регистры:
SP(StackPointer) – указатель текущей позиции в стеке.
BP(BasePointer) – дополнительный указатель.
SI (Source Index) – индекс источника.
DI (Destination Index) – индекс приемника.
IP(InstructionPointer) – указатель текущей позиции выполняемой программы.
Кроме указанных, существует т.н. регистр флагов, содержащий информацию о результате выполнения последней операции. Он рассматривается как набор бит (флагов), каждый из которых имеет строго определенное значение:
CF (Carry Flag) – флаг переноса. Устанавливается (т.е. принимает значение 1) в том случае, если в результате выполнения последней операции произошел перенос бита из старшего разряда (напр., при вычитании большего числа из меньшего).
OF(OverflowFlag) – флаг переполнения. Устанавливается, если в результате арифметической операции произошло переполнение регистра.
DF(DirectionFlag) – флаг направления. Управляет направлением повторения операций (например, при побайтовом перемещении данных): справа налево или наоборот.
IF (Interrupt Flag) - флаг прерываний. Контролирует возможность прерываний: разрешены они или временно запрещены
SF (Sign Flag) – флаг знака. Принимает значение старшего бита (бита знака) результата операции.
ZF(ZeroFlag) – флаг нуля. Указывает на нулевой результат (или равенство при сравнении).
AF(AdditioncarryFlag) - флаг дополнительного переноса. Сигнализирует о переносе бита из младшей тетрады байта в старшую. Тетрадой называются 4 бита, составляющие половину байта. Первые 4 бита (т.е. биты 7..4) называются старшей тетрадой, последние (биты 3..0) – младшей.
PF (Parity Flag) – флаг четности. Устанавливается, если число бит результата – четное.
Организация памяти.
Память в MS-DOSделится на сегменты по 64К каждый. Сегменты могут «наслаиваться» друг на друга, следовать друг за другом или совпадать. Любая программа занимает как минимум один сегмент – сегмент кода. Его адрес хранится в регистреCS. Кроме того, зачастую приходится использовать сегмент данных (регистрDS). Адресация внутри сегмента называется индексной. Для обращения к любому байту (или слову (word), или двойному слову (dword–doubleword)) используется формат записи:сегментный_регистр:[индексный_регистр]. В качестве индексных в некоторых случаях могут использоваться регистрыBXиDX.
Команды языка Ассемблер.
Любая команда ассемблера представляется в памяти машины в виде управляющего набора байт. Все команды располагаются в сегменте кода. Каждая команда может иметь до двух операндов, которые определяют ее направленность. Т.е. команда использует операнды для выполнения каких-либо действий, которые, в частности, могут вызвать изменения значений операндов. Если синтаксис команды предусматривает 2 операнда, то первый из них, будет являться приемником результата, а второй (или оба) – источником данных. Команды, использующие один операнд, могут работают с ним и как с источником, и как с приемником. Напр.:
Mov ax, 3 ; пересылка в AX числа 3 (т.е. AX - приемник)
Add bx, ax ; суммирование содержимого регистров AX и BX и запись результата в BX
Inc dh ; увеличение содержимого DH на 1 (инкрементирование)
Push cx ; занесение («заталкивание») в стек содержимого CX (CX не изменяется)
Ret ; возврат из процесса – программы или подпрограммы (операнды не требуются)
Для создания программы, помимо команд, требуются т.н. директивы компилятора, указывающие компилятору TASM(TurboASseMblerфирмыBorland) методику формирования исполняемого файла. К таким директивам относятся:
.model тип_моделиУказывает, сколько сегментов будет использовать программа.Тип_моделиможет принимать значенияtiny(один сегмент для данных и кода),small(один сегмент кода и один - данных),flat,largeиhuge. В дальнейшей работе будут использоваться только моделиtinyиsmall.
.data Начало сегмента данных. Здесь могут располагаться переменные, массивы и пр.
.codeНачало сегмента кода. Все инструкции, процедуры и данные, помещенные после этой директивы, будут находиться в сегменте кода.
.startup «Точка входа» программы. После этой строки начинается непосредственно выполнение программы.
end Конец программы. После этой строки весь последующий текст игнорируется.
&&&
$$$003-001-002$3.3.1.2 Задания или тестовые вопросы для самоконтроля к занятию №1
Перейти в каталог, содержащий файлы tasm.exeиtlink.exe. Создать новый текстовый файл с помощью любого текстового редактора (например, встроенного редактораNortonCommander).
Набрать текст:
.model tiny
.code
.startup
ret
end
Сохранить файл, выйти из редактора, выполнить команду
tasm имя_файла
Проанализировать выданные программой сообщения. Проверить наличие в текущем каталоге файла с заданным Вами именем и расширением .obj. В случае отсутствия такового проверить предыдущие шаги, исправить ошибки.
Выполнить команду
tlink /t имя_файла
Убедиться в появлении нового .com-файла, запустить его, проанализировать результат его выполнения.
Запустить NortonGuides(ng.exe), научиться вызывать резидентную программу (Shift+F1).
Пользуясь NortonGuidesкак справочником, составить программу, суммирующую два числа и вычитающую из полученного результата число 3 (без интерактивного ввода данных и без отображения результата на экране).
Отладить программу, создать .com-файл.
Запустить insight.com, изучить его главное меню (F10), загрузить вновь созданный .com-файл, проверить правильность его работы путем пошаговой отладки (F8).
Изучить и проанализировать изменения, происходящие с регистрами в процессе отладки, объяснить эти изменения.
&&&
$$$003-002-000$3.3.2 Практическое занятие №2
Объявление переменных
&&&
$$$003-002-001$3.3.2.1 Методические указания к практическому занятию №2
. Данная лабораторная работа служит для ознакомления студентов с методикой адресации памяти при программировании на языке ассемблера, овладения навыками создания переменных и массивов, а также работы с ними. Также обзорно рассматривается организация простейшего цикла со счетчиком.
Для объявления переменной (или массива переменных) в Турбо Ассемблере используются специальные идентификаторы типа, характеризующие размер создаваемой переменной. К таким идентификаторам относятся:
DB(DimensionByte) – объявление переменной размером в 1 байт
DW(DimensionWord) – объявление переменной размером в 2 байта (машинное слово)
DD(DimensionDoubleword) – объявление переменной размером в 4 байта (двойное слово)
DQ(DimensionQuadrupleword) - объявление переменной размером в 8 байт (4 слова)
Синтаксис объявления переменной:
имя_переменной тип начальное_значение
где начальное_значениеможет являться любым числом из диапазона, допустимого данным типом. Запись числа может осуществляться в десятичном, в шестнадцатеричном, в восьмеричном или двоичном формате путем добавления к цифре буквы – идентификатора счисления. Используются следующие буквы:
d(Decimal) – число является десятичным. Этот идентификатор можно опускать, т.к. любое число без завершающей буквы считается десятичным по умолчанию, т.е. запись 034dэквивалентна обычной записи 34.
h(Hex) – число является шестнадцатеричным. Например: 3е5ah, 0ac44h, 0f0h. В случае, когда число начинается с буквы (a,b,c,d,e,f,A,B,C,D,E,F), ему должен предшествовать незначащий ноль.
o(Octal) – число является восьмеричным. Цифры, допустимые в записи – 0,1,2,3,4,5,6,7.
b(Binary) – число является двоичным. Допустимые в записи цифры – 0 и 1.
Помимо явно указанного числа, в качестве начального значения может использоваться запись в одинарных кавычках (в этом случае числом является ASCII-код находящегося в кавычках символа/символов) или символ вопроса (?). Если в качестве начального значения указан вопросительный знак, то это значение считается неопределенным.
Пример объявлений переменных:
a db 3;переменная а занимает 1 байт и первоначально равна трем
MyVar dw 0cf4h;MyVarимеет размерность машинного слова с начальным; шестнадцатеричным значением 0cf4
Symbol db ‘k’;Однобайтовой переменнойSymbolприсвоено значение 107 (код буквы ‘k’)
LongInt dd ?; Четырехбайтовая переменнаяLongIntфиксированного начального значения;не имеет