THE BELL

Есть те, кто прочитали эту новость раньше вас.
Подпишитесь, чтобы получать статьи свежими.
Email
Имя
Фамилия
Как вы хотите читать The Bell
Без спама

Программирование на уровне машинных команд - это тот минимальный уровень, на котором возможно составление программ. Система машинных команд должна быть достаточной для того, чтобы реализовать требуемые действия, выдавая указания аппаратуре вычислительной машины.

Каждая машинная команда состоит из двух частей:

  • операционной — определяющей, «что делать»;
  • операндной — определяющей объекты обработки, «с чем делать».

Машинная команда микропроцессора, записанная на языке ассемблера, представляет собой одну строку, имеющую следующий синтакический вид:

метка команда/директива операнд(ы) ;комментарии

При этом обязательным полем в строке является команда или директива.

Метка, команда/директива и операнды (если имеются) разделяются по крайней мере одним символом пробела или табуляции.

Если команду или директиву необходимо продолжить на следующей строке, то используется символ обратный слеш: \.

По умолчанию язык ассемблера не различает заглавные и строчные буквы в написании команд или директив.

Примеры строк кода:

Count db 1 ;Имя, директива, один операнд
mov eax,0 ;Команда, два операнда
cbw ; Команда

Метки

Метка в языке ассемблера может содержать следующие символы:

  • все буквы латинского алфавита;
  • цифры от 0 до 9;
  • спецсимволы: _, @, $, ?.

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

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

Команды

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

Директивы

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

Операнды

Операнд – объект, над которым выполняется машинная команда или оператор языка программирования.
Команда может иметь один или два операнда, или вообще не иметь операндов. Число операндов неявно задается кодом команды.
Примеры:

  • Нет операндов ret ;Вернуться
  • Один операнд inc ecx ;Увеличить ecx
  • Два операнда add eax,12 ;Прибавить 12 к eax

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

В качестве операндов могут выступать

  • идентификаторы;
  • цепочки символов, заключенных в одинарные или двойные кавычки;
  • целые числа в двоичной, восьмеричной, десятичной или шестнадцатеричной системе счисления.
Идентификаторы

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

Правила записи идентификаторов.

  • Идентификатор может состоять из одного или нескольких символов.
  • В качестве символов можно использовать буквы латинского алфавита, цифры и некоторые специальные знаки: _, ?, $, @.
  • Идентификатор не может начинаться символом цифры.
  • Длина идентификатора может быть до 255 символов.
  • Транслятор воспринимает первые 32 символа идентификатора, а остальные игнорирует.
Комментарии

Комментарии отделяются от исполняемой строки символом; . При этом все, что записано после символа точка с запятой и до конца строки, является комментарием. Использование комментариев в программе улучшает ее ясность, особенно там, где назначение набора команд непонятно. Комментарий может содержать любые печатные символы, включая пробел. Комментарий может занимать всю строку или следовать за командой на той же строке.

Структура программы на ассемблере

Программа, написанная на языке ассемблера, может состоять из нескольких частей, называемых модулями . В каждом модуле могут быть определены один или несколько сегментов данных, стека и кода. Любая законченная программа на ассемблере должна включать один главный, или основной, модуль, с которого начинается ее выполнение. Модуль может содержать сегменты кода, сегменты данных и стека, объявленные при помощи соответствующих директив. Перед объявлением сегментов нужно указать модель памяти при помощи директивы.MODEL.

Пример «ничего не делающей» программы на языке ассемблера:

686P
.MODEL FLAT, STDCALL
.DATA
.CODE
START:

RET
END START

В данной программе представлена всего одна команда микропроцессора. Эта команда RET . Она обеспечивает правильное окончание работы программы. В общем случае эта команда используется для выхода из процедуры.
Остальная часть программы относится к работе транслятора.
.686P — разрешены команды защищенного режима Pentium 6 (Pentium II). Данная директива выбирает поддерживаемый набор команд ассемблера, указывая модель процессора. Буква P, указанная в конце директивы, сообщает транслятору о работе процессора в защищенном режиме.
.MODEL FLAT, stdcall — плоская модель памяти. Эта модель памяти используется в операционной системе Windows. stdcall
.DATA — сегмент программы, содержащий данные.
.CODE — блок программы, содержащей код.
START — метка. В ассемблере метки играют большую роль, что не скажешь о современных языках высокого уровня.
END START — конец программы и сообщение транслятору, что начинать выполнение программы надо с метки START .
Каждый модуль должен содержать директиву END , отмечающую конец исходного кода программы. Все строки, которые следуют за директивой END , игнорируются. Если опустить директиву END , то генерируется ошибка.
Метка, указанная после директивы END , сообщает транслятору имя главного модуля, с которого начинается выполнение программы. Если программа содержит один модуль, метку после директивы END можно не указывать.

Тема 1.4 Ассемблерная мнемоника. Структура и форматы команд. Виды адресации. Система команд микропроцессора

План:

1 Язык ассемблера. Основные понятия

2 Символы языка ассемблера

3 Типы операторов ассемблера

4 Директивы ассемблера

5 Система команд процессора

1 Я зык ассемблера. Основные понятия

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

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

Предложения ассемблера бывают четырех типов:

1) команды или инструкции, представляющие собой символические аналоги машинных команд. В процессе трансляции инструкции ассемблера преобразуются в соответствующие команды системы команд микропроцессора;

2) макрокоманды - оформляемые определенным образом предложения текста программы, замещаемые во время трансляции другими предложениями;

3) директивы, являющиеся указанием транслятору ассемблера на выполнение некоторых действий. У директив нет аналогов в машинном представлении;

4) строки комментариев , содержащие любые символы, в том числе и буквы русского алфавита. Комментарии игнорируются транслятором.

­ Структура программы на ассемблере. Синтаксис ассемблера.

Предложения, составляющие программу, могут представлять собой синтаксическую конструкцию, соответствующую команде, макрокоманде, директиве или комментарию. Для того чтобы транслятор ассемблера мог распознать их, они должны формироваться по определенным синтаксическим правилам. Для этого лучше всего использовать формальное описание синтаксиса языка наподобие правил грамматики. Наиболее распространенные способы подобного описания языка программирования - синтаксические диаграммы и расширенные формы Бэкуса-Наура. Для практического использования более удобны синтаксические диаграммы. К примеру, синтаксис предложений ассемблера можно описать с помощью синтаксических диаграмм, показанных на следующих рисунках 10, 11, 12.

Рисунок 10 - Формат предложения ассемблера


­ Рисунок 11 - Формат директив

­ Рисунок 12 - Формат команд и макрокоманд

На этих рисунках:

­ имя метки - идентификатор, значением которого является адрес первого байта того предложения исходного текста программы, которое он обозначает;

­ имя - идентификатор, отличающий данную директиву от других одноименных директив. В результате обработки ассемблером определенной директивы этому имени могут быть присвоены определенные характеристики;

­ код операции (КОП) и директива - это мнемонические обозначения соответствующей машинной команды, макрокоманды или директивы транслятора;

­ операнды - части команды, макрокоманды или директивы ассемблера, обозначающие объекты, над которыми производятся действия. Операнды ассемблера описываются выражениями с числовыми и текстовыми константами, метками и идентификаторами переменных с использованием знаков операций и некоторых зарезервированных слов.

Синтаксические диаграммы помогают найти и затем пройти путь от входа диаграммы (слева) к ее выходу (направо). Если такой путь существует, то предложение или конструкция синтаксически правильные. Если такого пути нет, значит эту конструкцию компилятор не примет.

­ 2 Символы языка ассемблера

Допустимыми символами при написании текста программ являются:

1) все латинские буквы: A-Z , a-z . При этом заглавные и строчные буквы считаются эквивалентными;

2) цифры от 0 до 9 ;

3) знаки ? , @ , $ , _ , & ;

4) разделители , . () < > { } + / * % ! " " ? = # ^ .

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

Лексемами являются:

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

2) цепочки символов - последовательности символов, заключенные в одинарные или двойные кавычки;

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

4) десятичные числа не требуют для своего отождествления указания каких-либо дополнительных символов, например 25 или 139. Для отождествления в исходном тексте программы двоичных чисел необходимо после записи нулей и единиц, входящих в их состав, поставить латинское “b ”, например 10010101b .

5) шестнадцатеричные числа имеют больше условностей при своей записи:

Во-первых, они состоят из цифр 0...9 , строчных и прописных букв латинского алфавита a , b , c , d , e , f или A , B , C , D , E , F .

Во-вторых, у транслятора могут возникнуть трудности с распознаванием шестнадцатеричных чисел из-за того, что они могут состоять как из одних цифр 0...9 (например, 190845), так и начинаться с буквы латинского алфавита (например, ef15 ). Для того чтобы "объяснить" транслятору, что данная лексема не является десятичным числом или идентификатором, программист должен специальным образом выделять шестнадцатеричное число. Для этого на конце последовательности шестнадцатеричных цифр, составляющих шестнадцатерич-ное число, записывают латинскую букву “h ”. Это обязательное условие. Если шестнадцатеричное число начинается с буквы, то перед ним записывается ведущий ноль: 0 ef15h.

Практически каждое предложение содержит описание объекта, над которым или при помощи которого выполняется некоторое действие. Эти объекты называются операндами . Их можно определить так: операнды - это объекты (некоторые значения, регистры или ячейки памяти), на которые действуют инструкции или директивы, либо это объекты, которые определяют или уточняют действие инструкций или директив.

Возможно, провести следующую классификацию операндов:

­ постоянные или непосредственные операнды;

­ адресные операнды;

­ перемещаемые операнды;

­ счетчик адреса;

­ регистровый операнд;

­ базовый и индексный операнды;

­ структурные операнды;

­ записи.

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

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

­ 3 Типы операторов ассемблера

Перечислим возможные типы операторов ассемблера и синтаксические правила формирования выражений ассемблера:

­ арифметические операторы;

­ операторы сдвига;

­ операторы сравнения;

­ логические операторы;

­ индексный оператор;

­ оператор переопределения типа;

­ оператор переопределения сегмента;

­ оператор именования типа структуры;

­ оператор получения сегментной составляющей адреса выражения;

­ оператор получения смещения выражения.

1 Директивы ассемблера

­ Директивы ассемблера бывают:

1) Директивы сегментации. В ходе предыдущего обсуждения мы выяснили все основные правила записи команд и операндов в программе на ассемблере. Открытым остался вопрос о том, как правильно оформить последовательность команд, чтобы транслятор мог их обработать, а микропроцессор - выполнить.

При рассмотрении архитектуры микропроцессора мы узнали, что он имеет шесть сегментных регистров, посредством которых может одновременно работать:

­ с одним сегментом кода;

­ с одним сегментом стека;

­ с одним сегментом данных;

­ с тремя дополнительными сегментами данных.

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


­ Рисунок 13 - Синтаксическое описание сегмента на ассемблере

Важно отметить, что функциональное назначение сегмента несколько шире, чем простое разбиение программы на блоки кода, данных и стека. Сегментация является частью более общего механизма, связанного с концепцией модульного программирования. Она предполагает унификацию оформления объектных модулей, создаваемых компилятором, в том числе с разных языков программирования. Это позволяет объединять программы, написанные на разных языках. Именно для реализации различных вариантов такого объединения и предназначены операнды в директиве SEGMENT.

2) Директивы управления листингом. Директивы управления листингом делятся на следующие группы:

­ общие директивы управления листингом;

­ директивы вывода в листинг включаемых файлов;

­ директивы вывода блоков условного ассемблирования;

­ директивы вывода в листинг макрокоманд;

­ директивы вывода в листинг информации о перекрестных ссылках;

­ директивы изменения формата листинга.

2 Система команд процессора

Система команд процессора представлена на рисунке 14.

Рассмотрим основные группы команд.

­ Рисунок 14 - Классификация команд ассемблера

Команды бывают:

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

­ сохранение в памяти содержимого внутренних регистров процессора;

­ копирование содержимого из одной области памяти в другую;

­ запись в устройства ввода/вывода и чтение из устройств ввода/вывода.

В некоторых процессорах все эти функции выполняются одной единственной командой MOV (для байтовых пересылок - MOVB ) но с различными методами адресации операндов.

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

2 Арифметические команды. Арифметические команды рассматривают коды операндов как числовые двоичные или двоично-десятичные коды. Эти команды могут быть разделены на пять основных групп:

­ команды операций с фиксированной запятой (сложение, вычитание, умножение, деление);

­ команды операций с плавающей запятой (сложение, вычитание, умножение, деление);

­ команды очистки;

­ команды инкремента и декремента;

­ команда сравнения.

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

4 Команды очистки предназначены для записи нулевого кода в регистр или ячейку памяти. Эти команды могут быть заменены командами пересылки нулевого кода, но специальные команды очистки обычно выполняются быстрее, чем команды пересылки.

5 Команды инкремента (увеличения на единицу) и декремента

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

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

7 Логические команды. Логические команды выполняют над операндами логические (побитовые) операции, то есть они рассматривают коды операндов не как единое число, а как набор отдельных битов. Этим они отличаются от арифметических команд. Логические команды выполняют следующие основные операции:

­ логическое И, логическое ИЛИ, сложение по модулю 2 (Исключающее ИЛИ);

­ логические, арифметические и циклические сдвиги;

­ проверка битов и операндов;

­ установка и очистка битов (флагов) регистра состояния процессора (PSW ).

Команды логических операций позволяют побитно вычислять основные логические функции от двух входных операндов. Кроме того, операция И используется для принудительной очистки заданных битов (в качестве одного из операндов при этом используется код маски, в котором разряды, требующие очистки, установлены в нуль). Операция ИЛИ применяется для принудительной установки заданных битов (в качестве одного из операндов при этом используется код маски, в котором разряды, требующие установки в единицу, равны единице). Операция «Исключающее ИЛИ» используется для инверсии заданных битов (в качестве одного из операндов при этом применяется код маски, в котором биты, подлежащие инверсии, установлены в единицу). Команды требуют двух входных операндов и формируют один выходной операнд.

8 Команды сдвигов позволяют побитно сдвигать код операнда вправо (в сторону младших разрядов) или влево (в сторону старших разрядов). Тип сдвига (логический, арифметический или циклический) определяет, каково будет новое значение старшего бита (при сдвиге вправо) или младшего бита (при сдвиге влево), а также определяет, будет ли где-то сохранено прежнее значение старшего бита (при сдвиге влево) или младшего бита (при сдвиге вправо). Циклические сдвиги позволяют сдвигать биты кода операнда по кругу (по часовой стрелке при сдвиге вправо или против часовой стрелки при сдвиге влево). При этом в кольцо сдвига может входить или не входить флаг переноса. В бит флага переноса (если он используется) записывается значение старшего бита при циклическом сдвиге влево и младшего бита при циклическом сдвиге вправо. Соответственно, значение бита флага переноса будет переписываться в младший разряд при циклическом сдвиге влево и в старший разряд при циклическом сдвиге вправо.

9 Команды переходов. Команды переходов предназначены для организации всевозможных циклов, ветвлений, вызовов подпрограмм и т.д., то есть они нарушают последовательный ход выполнения программы. Эти команды записывают в регистр-счетчик команд новое значение и тем самым вызывают переход процессора не к следующей по порядку команде, а к любой другой команде в памяти программ. Некоторые команды переходов предусматривают в дальнейшем возврат назад, в точку, из которой был сделан переход, другие не предусматривают этого. Если возврат предусмотрен, то текущие параметры процессора сохраняются в стеке. Если возврат не предусмотрен, то текущие параметры процессора не сохраняются.

Команды переходов без возврата делятся на две группы:

­ команды безусловных переходов;

­ команды условных переходов.

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

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

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

­ переход, если равно нулю;

­ переход, если не равно нулю;

­ переход, если есть переполнение;

­ переход, если нет переполнения;

­ переход, если больше нуля;

­ переход, если меньше или равно нулю.

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

Специально для проверки условий перехода применяется команда сравнения (СМР), предшествующая команде условного перехода (или даже нескольким командам условных переходов). Но флаги могут устанавливаться и любой другой командой, например командой пересылки данных, любой арифметической или логической командой. Отметим, что сами команды переходов флаги не меняют, что как раз и позволяет ставить несколько команд переходов одну за другой.

Особое место среди команд перехода с возвратом занимают команды прерываний. Эти команды в качестве входного операнда требуют номер прерывания (адрес вектора).

Вывод:

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

Допустимыми символами при написании текста программ являются все латинские буквы: A-Z , a-z . При этом заглавные и строчные буквы считаются эквивалентными; цифры от 0 до 9 ; знаки ? , @ , $ , _ , & ; разделители , . () < > { } + / * % ! " " ? = # ^ .

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

Система команд разделена на 8 основных групп.

­ Контрольные вопросы:

1 Что представляет собой язык ассемблера?

2 Какие символы можно применять для записи команд на ассемблере?

3 Что представляют собой метки и их назначение?

4 Пояснить структуру команд ассемблера.

5 Перечислить 4 типа предложений ассемблера.

1. Архитектура ПК……………………………………………………………5

    1.1. Регистры.

    1.1.1 Регистры общего назначения.

1.1.2. Сегментные регистры

1.1.3 Регистр флагов

1.2. Организация памяти.

1.3. Представление данных.

1.3.1 Типы данных

1.3.2 Представление символов и строк

2. Операторы программы на ассемблере ……………………………………

    1. Команды языка ассемблера

2.2. Режимы адресации и форматы машинных команд

3. Псевдооператоры ………………………………………………………….

3.1 Директивы определения данных

3.2 Структура программы на ассемблере

3.2.1 Программные сегменты. Директива assume

3.2.3 Упрощенная директива сегментации

4. Ассемблирование и компоновка программы ………………………….

5. Команды пересылки данных…………………………………………….

    5.1 Команды общего назначения

    5.2 Команды работы со стеком

5.3 Команды ввода-вывода

5.4 Команды пересылки адреса

5.5 Команды пересылки флагов

6. Арифметические команды ……………………………………………….

    6.1 Арифметические операции над целыми двоичными числами

6.1.1 Сложение и вычитание

6.1.2 Команды приращения и уменьшения приемника на единицу

6.2 Умножение и деление

6.3 Изменение знака

7. Логические операции ………………………………………………….

8. Сдвиги и циклические сдвиги …………………………………………

9. Строковые операции …………………………………………………….

10. Логика и организация программ ………………………………………

10.1 Безусловные переходы

10.2 Условные переходы

10.4 Процедуры в языке ассемблера

10.5 Прерывания INT

10.6 Системное программное обеспечение

10.6.1.1 Чтение клавиатуры.

10.6.1.2 Вывод символов на экран

10.6.1.3 Завершение программ.

10.6.2.1 Выбор режимов дисплея

11. Дисковая память ……………………………………………………………..

11.2 Таблица распределения файлов

11.3 Операции ввода-вывода на диск

11.3.1 Запись файла на диск

11.3.1.1 Данные в формате ASCIIZ

11.3.1.2 Файловый номер

11.3.1.3 Создание дискового файла

11.3.2 Чтение дискового файла

Введение

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

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

Элементом подготовки программиста-профессионала обязательно является изучение ассемблера. Это связано с тем, что программирование на ассемблере требует знание архитектуры ПК, что позволяет создавать более эффективные программы на других языках и объединять их с программами на ассемблере.

В пособии рассматриваются вопросы программирования на языке ассемблера для компьютеров на базе микропрцессоров фирмы Intel.

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

    Архитектура ПК.

Архитектура ЭВМ – это абстрактное представление ЭВМ, которое отражает ее структурную, схемотехническую и логическую организацию.

Все современные ЭВМ обладают некоторыми общими и индивидуальными свойствами архитектуры. Индивидуальные свойства присущи только конкретной модели компьютера.

Понятие архитектуры ЭВМ включает в себя:

    структурную схему ЭВМ;

    средства и способы доступа к элементам структурной схемы ЭВМ;

    набор и доступность регистров;

    организацию и способы адресации;

    способ представления и формат данных ЭВМ;

    набор машинных команд ЭВМ;

    форматы машинных команд;

    обработка прерываний.

Основные элементы аппаратных средств компьютера: системный блок, клавиатура, устройства отображения, дисководы, печатающие устройства (принтер) и различные средства связи. Системный блок состоит из системной платы, блока питания и ячеек расширения для дополнительных плат. На системной плате размещены микропроцессор, постоянная память (ROM), оперативная память (RAM) и сопроцессор.

      Регистры.

Внутри микропроцессора информация содержится в группе из 32 регистров (16 пользовательских, 16 системных), в той или иной мере доступных для использования программистом. Так как пособие посвящено программированию для микропроцессора 8088-i486, то логичнее всего начать эту тему с обсуждения внутренних регистров микропроцессора, доступных для пользователя.

Пользовательские регистры используются программистом для написания программ. К этим регистрам относятся:

    восемь 32-битных регистров (регистры общего назначения) EAX/AX/AH/AL, EBX/BX/BH/BL, ECX/CX/CH/CL, EDX/DX/DLH/DL, EBP/BP, ESI/SI, EDI/DI, ESP/SP;

    шесть 16 -,битовых регистров сегментов: CS,DS, SS, ES, FS,GS;

    регистры состояния и управления: регистр флагов EFLAGS/FLAGS, и регистр указателя команды EIP/IP.

Через наклонную черту приведены части одного 32-разрядного регистра. Приставка E (Extended) обозначает использование 32-разраядного регистра. Для работы с байтами используются регистры с приставками L (low) и H(high), например, AL,CH - обозначающие младший и старший байты 16-разрядных частей регистров.

        Регистры общего назначения.

EAX/AX/AH/AL(Accumulator register) –аккумулятор . Используются при умножении и делении, в операциях ввода-вывода и в некоторых операциях над строками.

EBX/BX/BH/BL – базовый регистр (base register), часто используется при адресации данных в памяти.

ECX/CX/CH/CL – счетчик (count register), используется как счетчик числа повторений цикла.

EDX/DX/DH/DL –регистр данных (data register), используется для хранения промежуточных данных. В некоторых командах использование его обязательно.

Все регистры этой группы позволяют обращаться к своим «младшим» частям. Использование для самостоятельной адресации можно только младшие 16- и 8-битовые части этих регистров. Старшие 16 бит этих регистров как самостоятельные объекты недоступны.

Для поддержки команд обработки строк, позволяющих производить последовательную обработку цепочек элементов имеющих длину 32, 16 или 8 бит используются:

ESI/SI (source index register) – индекс источника . Содержит адрес текущего элемента источника.

EDI/DI (distination index register) – индекс приемника (получателя). Содержит текущий адрес в строке приемнике.

В архитектуре микропрцессора на программно-аппаратном уровне поддерживается структура данных – стек. Для работы со стеком есть специальные команды и специальные регистры. Следует отметить, что стек заполняется в сторону меньших адресов.

ESP/SP (stack poINTer register) –регистр указателя стека . Содержит указатель вершины стека в текущем сегменте стека.

EBP/BP (base poINTer register) –регистр указателя базы стека . Предназначен для организации произвольного доступа к данным внутри стека.

1.1.2. Сегментные регистры

В программной модели микропроцессора имеются шесть сегментных регистров: CS, SS, DS, ES, GS, FS. Их существование обусловлено спецификой организации и использования оперативной памяти микропроцессорами Intel. Микропроцессор аппаратно поддерживает структурную организацию программы состоящей из сегментов. Для указания сегментов доступных в данный момент предназначены сегментные регистры. Микропроцессор поддерживает следующие типы сегментов:

    Сегмент кода. Содержит команды программы Для доступа к этому сегменту служит регистр CS (code segment register) – сегментный регистр кода . Он содержит адрес сегмента с машинными командами, к которому имеет доступ микропроцессор.

    Сегмент данных. Содержит обрабатываемые программой данные. Для доступа к этому сегменту служит регистр DS (data segment register) – сегментный регистр данных , который хранит адрес сегмента данных текущей программы.

    Сегмент стека. Этот сегмент представляет собой область памяти, называемую стеком. Микропроцессор организует стек по принципу – первый «пришел», первый «ушел». Для доступа к стеку служит регистр SS (stack segment register) – сегментный регистр стека , содержащий адрес сегмента стека.

    Дополнительный сегмент данных. Обрабатываемые данные могут находиться еще в трех дополнительных сегментах данных. По умолчанию предполагается, что данные находятся в сегменте данных. При использовании дополнительных сегментов данных их адреса требуется указать явно с помощью специальных префиксов переопределения сегментов в команде. Адреса дополнительных сегментов данных должны содержаться в регистрах ES, GS, FS (extenSIon data segment registers).

        Регистры управления и состояния

Микропроцессор содержит несколько регистров, которые содержат информацию о состоянии, как самого микропроцессора, так и программы, команды которой в данный момент загружены в конвейер. Это:

Регистр указателя команд EIP/IP;

    регистр флагов EFLAGS/FLAGS.

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

EIP/IP (instruction poINTer register) –указатель команд . Регистр EIP/IP имеет разрядность 32 или 16 бит и содержит смещение следующей выполняемой команды относительно содержимого сегментного регистра CS в текущем сегменте команд. Этот регистр непосредственно недоступен, но изменение его производится командами перехода.

EFLAGS/FLAGS (Flag register) – регистр флагов . Разрядность 32/16 бит. Отдельные биты данного регистра имеют определенное функциональное назначение и называются флагами. Флаг - это бит, принимающий значение 1 ("флаг установлен"), если выполнено некоторое условие, и значение 0 ("флаг сброшен") в противном случае. Младшая часть этого регистра полностью аналогична регистру FLAGS для i8086.

1.1.3 Регистр флагов

Регистр флагов является 32-разрядным, имеет имя EFLAGS (рис.1). Отдельные биты регистра имеют определенное функциональное назначение и называются флагами. Каждому из них присвоено определенное имя (ZF, CF и т.д). Младшие 16 бит EFLAGS представляют 16-разрядный регистр флагов FLAGS, используемый при выполнении программ, написанных для микропроцессора i086 и i286.

Рис.1 Регистр флагов

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

Флаги условий:

CF (carry flag) - флаг переноса . Принимает значение 1, если при сложении целых чисел появилась единица переноса, не "влезающая" в разрядную сетку, или если при вычитании чисел без знака первое из них было меньше второго. В командах сдвига в CF заносится бит, вышедший за разрядную сетку. CF фиксирует также особенности команды умножения.

OF (overflow flag) - флаг переполнения . Устанавливается в 1, если при сложении или вычитании целых чисел со знаком получился результат, по модулю превосходящий допустимую величину (произошло переполнение мантиссы и она "залезла" в знаковый разряд).

ZF (zero flag) - флаг нуля . Устанавливается в 1, если результат команды оказался равным 0.

SF (SIgn flag) - флаг знака . Устанавливается в 1, если в операции над знаковыми числами получился отрицательный результат.

PF (parity flag) - флаг четности . Равен 1, если результат очередной команды содержит четное количество двоичных единиц. Учитывается обычно только при операциях ввода-вывода.

AF (auxiliary carry flag) - флаг дополнительного переноса . Фиксирует особенности выполнения операций над двоично-десятичными числами.

Флаги состояний:

DF (direction flag) - флаг направления . Устанавливает направление просмотра строк в строковых командах: при DF=0 строки просматриваются "вперед" (от начала к концу), при DF=1 - в обратном направлении.

IOPL (input/output privilege level) – уровень привилегий ввода-вывода. Используется в защищенном режиме работы микропроцессора, для контроля доступа к командам ввода-вывода, в зависимости от привилегированности задачи.

NT (nested task) – флаг вложенности задачи. Используется в защищенном режиме работы микропроцессора для фиксации того факта, что одна задача вложена в другую.

Системные флаг:

IF (INTerrupt flag) - флаг прерываний . При IF=0 процессор перестает реагировать на поступающие к нему прерывания, при IF=1 блокировка прерываний снимается.

TF (trap flag) - флаг трассировки . При TF=1 после выполнения каждой команды процессор делает прерывание (с номером 1), чем можно воспользоваться при отладке программы для ее трассировки.

RF (resume flag) – флаг возобновления . Используется при обработке прерываний от регистров отладки.

VM (virtuAL 8086 mode) – флаг виртуального 8086. 1-процессор работает в режиме виртуального 8086. 0- процессор работает в реальном или защищенном режиме.

AC (ALignment check) –флаг контроля выравнивания. Предназначен для разрешения контроля выравнивания при обращении к памяти.

      Организация памяти.

Физическая память, к которой микропроцессор имеет доступ, называется оперативной памятью (или оперативным запоминающим устройством - ОЗУ). ОЗУ представляет собой цепочку байтов, имеющих свой уникальный адрес (его номер), называемый физическим. Диапазон значений физических адресов от 0 до 4 Гбайт. Механизм управления памятью полностью аппаратный.

Микропроцессор аппаратно поддерживает несколько моделей использования оперативной памяти:

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

    страничную модель . В этом случае оперативная память рассматривается как совокупность блоков фиксированного размера 4 Кбайта. Основное применение этой модели связано с организацией виртуальной памяти, что позволяет использовать для работы программ пространство памяти большее, чем объем физической памяти. Для микропроцессора Pentium размер возможной виртуальной памяти может достигать 4 Тбайта.

Использование и реализация этих моделей зависит от режима работы микропроцессора:

    Режим реальных адресов (реальный режим). Режим аналогичный работе i8086 процессора. Необходим для функционирования программ, разработанных для ранних моделей процессоров.

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

    Режим виртуального 8086. В этом режиме появляется возможность работы нескольких программ для i8086. При этом возможна работа программ реального режима.

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

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

Формирование физического адреса в реальном режиме

В реальном режиме диапазон изменения физического адреса от 0 до 1 Мбайт. Максимальный размер сегмента 64 Кбайт. При обращении к конкретному физическому адресу оперативной памяти определяется адрес начала сегмента и смещение внутри сегмента. Адрес начала сегмента берется из соответствующего сегментного регистра. При этом в сегментном регистре содержатся только старшие 16 бит физического адреса начала сегмента. Недостающие младшие четыре бита 20-битного адреса получаются сдвигом значения сегментного регистра влево на 4 разряда. Операция сдвига выполняется аппаратно. Полученное 20-битное значение и является настоящим физическим адресом, соответствующим началу сегмента. То есть физический адрес задается как пара "сегмент:смещение",где "сегмент" (segment) - это первые16 битов начального адресасегмента памяти, которому принадлежитячейка, а "смещение" - 16-битовый адрес этой ячейки, отсчитанный от начала данного сегмента памяти (величина 16*сегмент+смещение дает абсолютный адрес ячейки). Если, например, в регистре CS хранится величина 1234h, тогда адресная пара 1234h:507h определяет абсолютный адрес, равный 16*1234h+507h =12340h+507h = 12847h. Такая пара записывается в виде двойного слова, причем (как и для чисел) в "перевернутом" виде: в первом слове размещается смещение, а вовтором - сегмент, причем каждое из этих словв свою очередь представлено в "перевернутом"виде. Например, пара 1234h:5678h будет записана так:| 78 | 56| 34 | 12|.

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

Структуры в языке ассемблер

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

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

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

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

По определению структура - это тип данных, состоящий из фиксированного числа элементов разного типа.

Для использования структур в программе необходимо выполнить три действия:

    Задать шаблон структуры .

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

    Определить экземпляр структуры .

    Этот этап подразумевает инициализацию конкретной переменной заранее определенной (с помощью шаблона) структурой.

    Организовать обращение к элементам структуры .

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

Описать структуру в программе означает лишь указать ее схему или шаблон; память при этом не выделяется.

Этот шаблон можно рассматривать лишь как информацию для транслятора о расположении полей и их значении по умолчанию.

Определить структуру - значит, дать указание транслятору выделить память и присвоить этой области памяти символическое имя.

Описать структуру в программе можно только один раз, а определить - любое количество раз.

Описание шаблона структуры

Описание шаблона структуры имеет следующий синтаксис:

имя_структуры STRUC

имя_структуры ENDS

Здесь представляет собой последовательность директив описания данных db, dw, dd, dq и dt .

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

Как мы уже отметили при описании шаблона, память не выделяется, так как это всего лишь информация для транслятора.

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

Рассмотрим работу со структурами на примере моделирования базы данных о сотрудниках некоторого отдела.

Для простоты, чтобы уйти от проблем преобразования информации при вводе, условимся, что все поля символьные.

Определим структуру записи этой базы данных следующим шаблоном:

Определение данных с типом структуры

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

[имя переменной] имя_структуры

    имя переменной - идентификатор переменной данного структурного типа.

    Задание имени переменной необязательно. Если его не указать, будет просто выделена область памяти размером в сумму длин всех элементов структуры.

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

    Его задание также необязательно.

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

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

    К примеру: victor worker .

Для примера определим несколько переменных с типом описанной выше структуры.

Методы работы со структурой

Идея введения структурного типа в любой язык программирования состоит в объединении разнотипных переменных в один объект.

В языке должны быть средства доступа к этим переменным внутри конкретного экземпляра структуры. Для того чтобы сослаться в команде на поле некоторой структуры, используется специальный оператор - символ " . " (точка) . Он используется в следующей синтаксической конструкции:

    адресное_выражение - идентификатор переменной некоторого структурного типа или выражение в скобках в соответствии с указанными ниже синтаксическими правилами (рис. 1);

    имя_поля_структуры - имя поля из шаблона структуры.

    Это, на самом деле, тоже адрес, а точнее, смещение поля от начала структуры.

Таким образом оператор ". " (точка) вычисляет выражение

Рис. 5. Синтаксис адресного выражения в операторе обращения к полю структуры

Продемонстрируем на примере определенной нами структуры worker некоторые приемы работы со структурами.

К примеру, извлечь в ax значения поля с возрастом. Так как вряд ли возраст трудоспособного человека будет больше величины 99 лет, то после помещения содержимого этого символьного поля в регистр ax его будет удобно преобразовать в двоичное представление командой aad .

Будьте внимательны, так как из-за принципа хранения данных “младший байт по младшему адресу” старшая цифра возраста будет помещена в al , а младшая - в ah .

Для корректировки достаточно использовать команду xchg al,ah :

mov ax,word ptr sotr1.age ;в al возраст sotr1

а можно и так:

Дальнейшая работа с массивом структур производится так же, как и с одномерным массивом. Здесь возникает несколько вопросов:

Как быть с размером и как организовать индексацию элементов массива?

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

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

К примеру:

Как выполнить копирование поля из одной структуры в соответствующее поле другой структуры? Или как выполнить копирование всей структуры? Давайте выполним копирование поля nam третьего сотрудника в поле nam пятого сотрудника:

mas_sotr worker 10 dup ()

mov bx,offset mas_sotr

mov si,(type worker)*2 ;si=77*2

mov di,(type worker)*4 ;si=77*4

Мне кажется, что ремесло программиста рано или поздно делает человека похожим на хорошую домохозяйку. Он, подобно ей, постоянно находится в поиске, где бы чего-нибудь сэкономить, урезать и из минимума продуктов сделать прекрасный обед. И если это удается, то и моральное удовлетворение получается ничуть не меньше, а может и больше, чем от прекрасного обеда у домохозяйки. Степень этого удовлетворения, как мне кажется, зависит от степени любви к своей профессии.

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

Наличие в языке следующих двух типов данных, наверное, объясняется стремлением “хозяйки” максимально эффективно использовать рабочую площадь стола (оперативной памяти) при приготовлении еды или для размещения продуктов (данных программы).

Структура команды на языке ассемблера Программирование на уровне машинных команд - это тот минимальный уровень, на котором возможно программирование компьютера. Система машинных команд должна быть достаточной для того, чтобы реализовать требуемые действия, выдавая указания аппаратуре машины. Каждая машинная команда состоит из двух частей: операционной, определяющей «что делать» и операндной, определяющей объекты обработки, то есть то «над чем делать» . Машинная команда микропроцессора, записанная на языке Ассемблера, представляет собой одну строку, имеющую следующий вид: метка команда/директива операнд(ы) ; комментарии Метка, команда/директива и операнд разделяются по крайней мере одним символом пробела или табуляции. Операнды команды разделяются запятыми.

Структура команды на языке ассемблера Команда ассемблера указывает транслятору, какое действие должен выполнить микропроцессор. Директивы ассемблера - параметры, заданные в тексте программы, влияющие на процесс ассемблирования или свойства выходного файла. Операнд определяет начальное значение данных (в сегменте данных) или элементы, над которыми выполняется действие по команде (в сегменте кода). Команда может иметь один или два операнда, или не иметь операндов. Число операндов неявно задается кодом команды. Если команду или директиву необходимо продолжить на следующей строке, то используется символ «обратный слеш»: «» . По умолчанию Ассемблер не различает заглавные и строчные буквы в написании команд и директив. Примеры директивы и команды Count db 1 ; Имя, директива, один операнд mov eax, 0 ; Команда, два операнда

Идентификаторы – последовательности допустимых символов, использующиеся для обозначения имен переменных и названий меток. Идентификатор может состоять из одного или нескольких следующих символов: все буквы латинского алфавита; цифры от 0 до 9; спецсимволы: _, @, $, ? . В качестве первого символа метки может использоваться точка. В качестве идентификаторов нельзя использовать зарезервированные имена ассемблера (директивы, операторы, имена команд). Первым символом идентификатора должна быть буква или спецсимвол. Максимальная длина идентификатора 255 символов, но транслятор воспринимает первые 32, остальные игнорирует. Все метки, которые записываются в строке, не содержащей директиву ассемблера, должны заканчиваться двоеточием «: » . Метка, команда (директива) и операнд не обязательно должны начинаться с какой-либо определенной позиции в строке. Рекомендуется записывать их в колонку для большей yдобочитаемости программы.

Метки Все метки, которые записываются в строке, не содержащей директиву ассемблера, должны заканчиваться двоеточием «: » . Метка, команда (директива) и операнд не обязательно должны начинаться с какой-либо определенной позиции в строке. Рекомендуется записывать их в колонку для большей yдобочитаемости программы.

Комментарии Использование комментариев в программе улучшает ее ясность, особенно там, где назначение набора команд непонятно. Комментарии начинаются на любой строке исходного модуля с символа «точка с запятой» (;). Все символы, находящиеся справа от «; » до конца строки, являются комментарием. Комментарий может содержать любые печатные символы, включая «пробел» . Комментарий может занимать всю строку или следовать за командой на той же строке.

Структура программы на языке ассемблера Программа, написанная на языке ассемблера, может состоять из нескольких частей, называемых модулями, в каждом из которых могут быть определены один или несколько сегментов данных, стека и кода. Любая законченная программа на языке ассемблере должна включать один главный, или основной, модуль, с которого начинается ее выполнение. Модуль может содержать программные сегменты, сегменты данных и стека, объявленные при помощи соответствующих директив.

Модели памяти Перед объявлением сегментов нужно указать модель памяти при помощи директивы. MODEL модификатор модель_памяти, соглашение_о_вызовах, тип_ОС, параметр_стека Основные модели памяти языка ассемблера: Модель памяти Адресация кода Адресация данных Операционная система Чередование кода и данных TINY NEAR MS-DOS Допустимо SMALL NEAR MS-DOS, Windows Нет MEDIUM FAR NEAR MS-DOS, Windows Нет COMPACT NEAR FAR MS-DOS, Windows Нет LARGE FAR MS-DOS, Windows Нет HUGE FAR MS-DOS, Windows Нет NEAR Windows 2000, Windows XP, Windows Допустимо FLAT NEAR NT,

Модели памяти Модель tiny работает только в 16 -разрядных приложениях MS-DOS. В этой модели все данные и код располагаются в одном физическом сегменте. Размер программного файла в этом случае не превышает 64 Кбайт. Модель small поддерживает один сегмент кода и один сегмент данных. Данные и код при использовании этой модели адресуются как near (ближние). Модель medium поддерживает несколько сегментов программного кода и один сегмент данных, при этом все ссылки в сегментах программного кода по умолчанию считаются дальними (far), а ссылки в сегменте данных - ближними (near). Модель compact поддерживает несколько сегментов данных, в которых используется дальняя адресация данных (far), и один сегмент кода с ближней адресацией (near). Модель large поддерживает несколько сегментов кода и несколько сегментов данных. По умолчанию все ссылки на код и данные считаются дальними (far). Модель huge практически эквивалентна модели памяти large.

Модели памяти Модель flat предполагает несегментированную конфигурацию программы и используется только в 32 -разрядных операционных системах. Эта модель подобна модели tiny в том смысле, что данные и код размещены в одном сегменте, только 32 -разрядном. Для разработки программы для модели flat перед директивой. model flat следует разместить одну из директив: . 386, . 486, . 586 или. 686. Выбор директивы выбора процессора определяет набор команд, доступный при написании программ. Буква p после директивы выбора процессора означает защищенный режим работы. Адресация данных и кода является ближней (near), при этом все адреса и указатели являются 32 -разрядными.

Модели памяти. MODEL модификатор модель_памяти, соглашение_о_вызовах, тип_ОС, параметр_стека Параметр модификатор используется для определения типов сегментов и может принимать значения: use 16 (сегменты выбранной модели используются как 16 -битные) use 32 (сегменты выбранной модели используются как 32 -битные). Параметр соглашение_о_вызовах используется для определения способа передачи параметров при вызове процедуры из других языков, в том числе и языков высокого уровня (C++, Pascal). Параметр может принимать следующие значения: C, BASIC, FORTRAN, PASCAL, SYSCALL, STDCALL.

Модели памяти. MODEL модификатор модель_памяти, соглашение_о_вызовах, тип_ОС, параметр_стека Параметр тип_ОС равен OS_DOS по умолчанию, и на данный момент это единственное поддерживаемое значение этого параметра. Параметр параметр_стека устанавливается равным: NEARSTACK (регистр SS равен DS, области данных и стека размещаются в одном и том же физическом сегменте) FARSTACK (регистр SS не равен DS, области данных и стека размещаются в разных физических сегментах). По умолчанию принимается значение NEARSTACK.

Пример «ничего не делающей» программы. 686 P. MODEL FLAT, STDCALL. DATA. CODE START: RET END START RET - команда микропроцессора. Она обеспечивает правильное окончание работы программы. Остальная часть программы относится к работе транслятора. . 686 P - разрешены команды защищенного режима Pentium 6 (Pentium II). Данная директива выбирает поддерживаемый набор команд ассемблера, указывая модель процессора. . MODEL FLAT, stdcall - плоская модель памяти. Эта модель памяти используется в операционной системе Windows. stdcall - используемое соглашение о вызовах процедур.

Пример «ничего не делающей» программы. 686 P. MODEL FLAT, STDCALL. DATA. CODE START: RET END START . DATA - сегмент программы, содержащий данные. Данная программа не использует стек, поэтому сегмент. STACK отсутствует. . CODE - сегмент программы, содержащей код. START - метка. END START - конец программы и сообщение компилятору, что начинать выполнение программы надо с метки START. Каждая программа должна содержать директиву END, отмечающую конец исходного кода программы. Все строки, которые следуют за директивой END, игнорируются Метка, указанная после директивы END, сообщает транслятору имя главного модуля, с которого начинается выполнение программы. Если программа содержит один модуль, метку после директивы END можно не указывать.

Трансляторы языка ассемблера Транслятор - программа или техническое средство, выполняющее преобразование программы, представленной на одном из языков программирования, в программу на целевом языке, называемую объектным кодом. Помимо поддержки мнемоник машинных команд, каждый транслятор обладает своим собственным набором директив и макросредств, зачастую ни с чем не совместимых. Основные виды трансляторов языка ассемблера: MASM (Microsoft Assembler), TASM (Borland Turbo Assembler), FASM (Flat Assembler) - свободно распространяемый многопроходной ассемблер, написанный Томашем Грыштаром (польск.), NASM (Netwide Assembler) - свободный ассемблер для архитектуры Intel x 86, был создан Саймоном Тэтхемом совместно с Юлианом Холлом и в настоящее время развивается небольшой командой разработчиков на Source. Forge. net.

Src="https://present5.com/presentation/-29367016_63610977/image-15.jpg" alt="Трансляция программы в Microsoft Visual Studio 2005 1) Создать проект, выбрав меню File->New->Project и"> Трансляция программы в Microsoft Visual Studio 2005 1) Создать проект, выбрав меню File->New->Project и указав имя проекта (hello. prj) и тип проекта: Win 32 Project. В дополнительных опциях мастера проекта указать “Empty Project”.

Src="https://present5.com/presentation/-29367016_63610977/image-16.jpg" alt="Трансляция программы в Microsoft Visual Studio 2005 2) В дереве проекта (View->Solution Explorer) добавить"> Трансляция программы в Microsoft Visual Studio 2005 2) В дереве проекта (View->Solution Explorer) добавить файл, в котором будет содержаться текст программы: Source. Files->Add->New. Item.

Трансляция программы в Microsoft Visual Studio 2005 3) Выбрать тип файла Code C++, но указать имя с расширением. asm:

Трансляция программы в Microsoft Visual Studio 2005 5) Установить параметры компилятора. Выбрать по правой кнопке в файле проекта меню Custom Build Rules…

Трансляция программы в Microsoft Visual Studio 2005 и в появившемся окне выбрать Microsoft Macro Assembler.

Трансляция программы в Microsoft Visual Studio 2005 Проверить по правой кнопке в файле hello. asm дерева проекта меню Properties и установить General->Tool: Microsoft Macro Assembler.

Src="https://present5.com/presentation/-29367016_63610977/image-22.jpg" alt="Трансляция программы в Microsoft Visual Studio 2005 6) Откомпилировать файл, выбрав Build->Build hello. prj."> Трансляция программы в Microsoft Visual Studio 2005 6) Откомпилировать файл, выбрав Build->Build hello. prj. 7) Запустить программу, нажав F 5 или выбрав меню Debug->Start Debugging.

Программирование в ОС Windows Программирование в OC Windows основывается на использовании функций API (Application Program Interface, т. е. интерфейс программного приложения). Их количество достигает 2000. Программа для Windows в значительной степени состоит из таких вызовов. Все взаимодействие с внешними устройствами и ресурсами операционной системы происходит, как правило, посредством таких функций. Операционная система Windows использует плоскую модель памяти. Адрес любой ячейки памяти будет определяться содержимым одного 32 -битного регистра. Возможны 3 типа структур программ для Windows: диалоговая (основное окно - диалоговое), консольная, или безоконная структура, классическая структура (оконная, каркасная).

Вызов функций Windows API В файле помощи любая функция API представлена в виде тип имя_функции (ФА 1, ФА 2, ФА 3) Тип – тип возвращаемого значения; ФАх – перечень формальных аргументов в порядке их следования Например, int Message. Box (HWND h. Wnd, LPCTSTR lp. Text, LPCTSTR lp. Caption, UINT u. Type); Данная функция выводит на экран окно с сообщением и кнопкой (или кнопками) выхода. Смысл параметров: h. Wnd -дескриптор окна, в котором будет появляться окно-сообщение, lp. Text - текст, который будет появляться в окне, lp. Caption - текст в заголовке окна, u. Type - тип окна, в частности можно определить количество кнопок выхода.

Вызов функций Windows API int Message. Box (HWND h. Wnd, LPCTSTR lp. Text, LPCTSTR lp. Caption, UINT u. Type); Практически все параметры API-функций в действительности 32 -битные целые числа: HWND - 32 -битное целое, LPCTSTR - 32 -битный указатель на строку, UINT - 32 -битное целое. К имени функций часто добавляется суффикс "А" для перехода к более новым версиям функций.

Вызов функций Windows API int Message. Box (HWND h. Wnd, LPCTSTR lp. Text, LPCTSTR lp. Caption, UINT u. Type); При использовании MASM необходимо в конце имени добавить @N N – количество байт, которое занимают в стеке переданные аргументы. Для функций Win 32 API это число можно определить как количество аргументов n, умноженное на 4 (байта в каждом аргументе): N=4*n. Для вызова функции используется команда CALL ассемблера. При этом все аргументы функции передаются в нее через стек (команда PUSH). Направление передачи аргументов: СЛЕВА НАПРАВО - СНИЗУ ВВЕРХ. Первым будет помещаться в стек аргумент u. Type. Вызов указанной функции будет выглядеть так: CALL Message. Box. A@16

Вызов функций Windows API int Message. Box (HWND h. Wnd, LPCTSTR lp. Text, LPCTSTR lp. Caption, UINT u. Type); Результат выполнения любой API функции - это, как правило, целое число, которое возвращается в регистре EAX. Директива OFFSET представляет собой «смещение в сегменте» , или, переводя в понятия языков высокого уровня, «указатель» начала строки. Директива EQU подобно #define в языке СИ определяет константу. Директива EXTERN указывает транслятору, что функция или идентификатор является внешним по отношению к данному модулю.

Пример программы «Привет всем!» . 686 P. MODEL FLAT, STDCALL. STACK 4096. DATA MB_OK EQU 0 STR 1 DB "Моя первая программа", 0 STR 2 DB "Привет всем!", 0 HW DD ? EXTERN Message. Box. A@16: NEAR. CODE START: PUSH MB_OK PUSH OFFSET STR 1 PUSH OFFSET STR 2 PUSH HW CALL Message. Box. A@16 RET END START

Директива INVOKE Транслятор языка MASM позволяет также упростить вызов функций с использованием макросредства – директивы INVOKE: INVOKE функция, параметр1, параметр2, … При этом нет необходимости добавлять @16 к вызову функции; параметры записываются точно в том порядке, в котором приведены в описании функции. макросредствами транслятора параметры помещаются в стек. для использования директивы INVOKE необходимо иметь описание прототипа функции с использованием директивы PROTO в виде: Message. Box. A PROTO: DWORD, : DWORD Если в программе используется множество функций Win 32 API, целесообразно воспользоваться директивой include C: masm 32includeuser 32. inc

THE BELL

Есть те, кто прочитали эту новость раньше вас.
Подпишитесь, чтобы получать статьи свежими.
Email
Имя
Фамилия
Как вы хотите читать The Bell
Без спама