Какой вид команды имеет на языке ассемблера. Основные сведения о языке Ассемблер

Какой вид команды имеет на языке ассемблера. Основные сведения о языке Ассемблер
Какой вид команды имеет на языке ассемблера. Основные сведения о языке Ассемблер

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

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

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

К примеру, ранее мы рассмотрели листинг 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

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

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

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

Курсоваяработа

По дисциплине «Системное программирование»

Тема №4: «Решение задач на процедуры»

Вариант 2

ВОСТОЧНО-СИБИРСКИЙ ГОСУДАРСТВЕННЫЙ УНИВЕРСИТЕТ

ТЕХНОЛОГИЙ И УПРАВЛЕНИЯ

____________________________________________________________________

ТЕХНОЛОГИЧЕСКИЙ КОЛЛЕДЖ

ЗАДАНИЕ

на курсовую работу

Дисциплина:
Тема: Решение задач на процедуры
Исполнитель(и):Главинская Арина Александровна
Руководитель:ДамбаеваСэсэгма Викторовна
Краткое содержание работы:изучение подпрограмм на языке Ассемблера,
решение задач с использованием подпрограмм
1. Теоретическая часть:Основные сведения о языке Ассемблер (набор
команд и т.д.), Организация подпрограмм, Способы передачи впараметров
в подпрограммах
2. Практическая часть:Разработать две подпрограммы, одна из которых преобразует любую заданную букву в заглавную (в том числе для русских букв), а другая преобразует букву в строчную.
преобразует любую заданную букву в заглавную, а другая преобразует букву в строчную.
преобразует букву в строчную.
Сроки выполнения проекта по графику:
1. Теоретическая часть - 30 % к 7 неделе.
2. Практическая часть - 70 % к 11 неделе.
3. Защита - 100% к 14 неделе.
Требования к оформлению:
1. Расчетно-пояснительная записка курсового проекта должна быть представлена в
электронной и твердой копиях.
2. Объем отчета должен быть не менее 20 машинописных страниц без учета приложений.
3. РПЗ оформляется по ГОСТу 7.32-91 и подписывается у руководителя.

Руководитель работы __________________

Исполнитель __________________

Дата выдачи "26 " сентября 2017 г.


Введение. 2

1.1 Основные сведения о языке Ассемблер. 3

1.1.1 Набор команд. 4

1.2 Организация подпрограмм в языке Ассемблер. 4

1.3 Способы передачи параметров в подпрограммах. 6

1.3.1 Передача параметров через регистры.. 6

1.3.2 Передача параметров через стек. 7

2 ПРАКТИЧЕСКИЙ РАЗДЕЛ.. 9

2.1 Постановка задачи. 9

2.2 Описание решения задачи. 9

2.3 Тестирование программы.. 7

Заключение. 8

Список литературы.. 9


Введение

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

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

Вторая область применения Ассемблера связана с оптимизацией выполнения программ. Очень часто программы-переводчики (компиляторы) с языков высокого уровня дают весьма неэффективную программу на машинном языке. Обычно это касается программ вычислительного характера, в которых большую часть времени выполняется очень небольшой (порядка 3-5%) участок программы (главный цикл). Для решения этой проблемы могут использоваться так называемые многоязыковые системы программирования, которые позволяют записывать части программы на различных языках. Обычно основная часть программы записывается на языке программирования высокого уровня (Фортране, Паскале, С и т.д.), а критические по времени выполнения участки программы – на Ассемблере. Скорость работы всей программы при этом может значительно увеличиться. Часто это единственный способ заставить программу дать результат за приемлемое время.

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

Задачи работы:

1. Изучить основные сведения о языке Ассемблер (структура и компоненты программы на Ассемблере, формат команд, организация подпрограмм и др.);

2. Изучить виды битовых операций, формат и логику работы логических команд Ассемблера;

3. Решить индивидуальную задачу на применение подпрограмм в Ассемблере;

4.. Сформулировать вывод о проделанной работе.

1 ТЕОРЕТИЧЕСКИЙ РАЗДЕЛ

Основные сведения о языке Ассемблер

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

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

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

Достоинства и недостатки

· минимальное количество избыточного кода (использование меньшего количества команд и обращений в память). Как следствие - большая скорость и меньший размер программы;

· большие объемы кода, большое число дополнительных мелких задач;

· плохая читабельность кода, трудность поддержки (отладка, добавление возможностей);

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

· меньшее количество доступных библиотек, их малая совместимость;

· непосредственный доступ к аппаратуре: портам ввода-вывода, особым регистрам процессора;

· максимальная «подгонка» для нужной платформы (использование специальных инструкций, технических особенностей «железа»);

· непереносимость на другие платформы (кроме двоично совместимых).

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

· определение данных (констант и переменных);

· управление организацией программы в памяти и параметрами выходного файла;

· задание режима работы компилятора;

· всевозможные абстракции (т.е. элементы языков высокого уровня) - от оформления процедур и функций (для упрощения реализации парадигмы процедурного программирования) до условных конструкций и циклов (для парадигмы структурного программирования);

· макросы.

Набор команд

Типичными командами языка ассемблера являются:

· Команды пересылки данных (mov и др.)

· Арифметические команды (add, sub, imul и др.)

· Логические и побитовые операции (or, and, xor, shr и др.)

· Команды управления ходом выполнения программы (jmp, loop, ret и др.)

· Команды вызова прерываний (иногда относят к командам управления): int

· Команды ввода-вывода в порты (in, out)

Для микроконтроллеров и микрокомпьютеров характерны также команды, выполняющие проверку и переход по условию, например:

· jne - перейти, если не равно;

· jge - перейти, если больше или равнo .

Команды языка Ассемблер (Лекция)

ПЛАН ЛЕКЦИИ

1. Основные группы операций.

Pentium .

1. Основные группы операций

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

Операциипересылки,

Арифметическиеоперации,

Логическиеоперации,

Операциисдвига,

Операциисравненияитестирования,

Битовыеоперации,

Операцииуправления программой;

Операцииуправления процессором.

2. Мнемокоды команд процессора Pentium

При описании команд обычно используются их мнемонические обозначения (мнемокоды), которые служат для задания команды при программировании на языке Ассемблера. Для различных версий Ассемблера мнемокоды некоторых команд могут отличаться. Например, для команды вызова подпрограммы используется мнемокод CALL или JSR (“ Jump to SubRoutine ”). Однако мнемокоды большинства команд для основных типов микропроцессоров совпадают или отличаются незначительно, так как они являются сокращениями соответствующих английских слов, определяющих выполняемую операцию. Рассмотрим мнемокоды команд, принятые для процессоров Pentium .

Команды пересылки. Основной командой этой группы является команда MOV , которая обеспечивает пересылку данных между двумя регистрами или между регистром и ячейкой памяти. В некоторых микропроцессорах реализуется пересылка между двумя ячейками памяти, а также групповая пересылка содержимого нескольких регистровиз памяти. Например, микропроцессоры семейства 68 xxx компании Motorola выполняют команду MOVE , обеспечивающую пересылку из одной ячейки памяти в другую, и команду MOVEM , которая производит запись в память или загрузку из памяти содержимого заданного набора регистров (до 16 регистров). Команда XCHG производит взаимный обмен содержимым двух регистров процессора или регистра и ячейки памяти.

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

Команды арифметических операций. Основными в этой группе являются команды сложения, вычитания, умножения и деления,которыеимеютрядвариантов. Команды сложения ADD и вычитания SUB выполняют соответствующие операции с c одержимым двух регистров, регистра и ячейки памяти или с использованием непосредственного операнда. Команды AD C , SB B производят сложение и вычитание с учетом значения признака C , устанавливаемого при формировании переноса в процессе выполнения предыдущей операции. С помощью этих команд реализуется последовательное сложение операндов, число разрядов которых превышает разрядность процессора. Команда NEG изменяет знак операнда, переводя его в дополнительный код.

Операции умножения и деления могут выполняться над числами со знаком (команды I MUL, I DIV ) или беззнака(команды MUL, DIV ).Одинизоперандоввсегдаразмещаетсяврегистре, второй может находиться в регистре, ячейке памяти или быть непосредственным операндом. Результат операции располагается в регистре. При умножении (команды MUL , IMUL ) получается результат удвоенной разрядности, для размещения которого используется два регистра. При делении (команды DIV , IDIV ) в качестве делимого используется операнд удвоенной разрядности, размещаемый в двух регистрах, а в качестве результата в два регистра записывается частное и остаток.

Команды логических операций . Практически все микропроцессоры производят логические операцииИ , ИЛИ, Исключающее ИЛИ, которые выполняются над одноименными разрядами операндов с помощью команд AND, OR, X OR . Операции выполняются над содержимым двух регистров, регистра и ячейки памяти или с использованием непосредственного операнда. Команда NOT инвертирует значение каждого разряда операнда.

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

Команды сравнения и тестирования . Сравнение операндов обычно производится с помощью команды CMP , которая производит вычитание операндов с установкой значений признаков N, Z, V, C в регистре состояния в соответствии с полученным результатом. При этом результат вычитания не сохраняется, и значения операндов не изменяются. Последующий анализ полученных значений признаков позволяет определить относительное значение (>, <, =) операндов со знаком или без знака. Использование различных способов адресации позволяет производит сравнение содержимого двух регистров, регистра и ячейки памяти, непосредственно заданного операнда с содержимым регистра или ячейки памяти.

Некоторые микропроцессоры выполняют команду тестирования TST , которая является однооперандным вариантом команды сравнения. При выполнении этой командыустанавливаются признаки N, Z в соответствии со знаком и значением (равно или не равно нулю) адресуемого операнда.

Команды битовых операций . Эти команды производят установку значения признака C в регистре состояний в соответствии со значением тестируемого бита bn в адресуемом операнде. В некоторых микропроцессорах по результату тестирования бита производится установка признака Z . Номер тестируемого бита n задаетсялибо содержимым указанного в команде регистра, либо непосредственным операндом.

Команды данной группы реализуют разные варианты изменениятестируемогобита.КомандаBT сохраняет значение этого бита неизменным .КомандаB T S послетестирования устанавливает значениеbn =1, а команда B T C - значение bn =0.Команда B T C инвертирует значение бита bn после его тестирования.

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

- команды безусловной передачи управления;

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

- команды организации программных циклов;

- команды прерывания;

- команды изменения признаков.

Безусловная передача управления производится командой JMP , которая загружает в программный счетчик PC новое содержимое, являющееся адресом следующей выполняемой команды. Этот адрес либо непосредственно указывается в команде JMP (прямая адресация), либо вычисляется как сумма текущего содержимого PC и заданного в команде смещения, которое является числом со знаком (относительная адресация). Так как PC содержит адрес очередной команды программы, то последний способ задает адрес перехода, смещенный относительно очередного адреса на заданное число байтов. При положительном смещении производится переход к последующим командам программы, при отрицательном смещении – к предыдущим.

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

Команды управления признаками обеспечивают запись - чтение содержимого регистра состояния, в котором хранятся признаки, а также изменение значений отдельных признаков. Например, в процессорах Pentium реализуются команды LAHF и SAHF , которые выполняют загрузку младшего байта, где содержатся признаки, из регистра состояния EFLAG в младший байт регистра EAX и заполнение младшего байта EFLAGS из регистра E A X .. Команды CLC, STC осуществляют установку значений признака переноса CF=0, CF=1, а команда CMC вызывает инвертирование значения этого признака. Так как признаки определяют ход выполнения программы при условных переходах, то команды изменения признаков обычно используются для управления программой.

Командыуправления процессором . К этой группе относятся команды останова, отсутствия операции и ряд команд, определяющих режим работы процессора или его отдельных блоков. Команда HLT прекращает выполнение программы и переводит процессор в состояние останова, выход из которого происходит при поступлении сигналов прерывания или перезапуска (Reset ). Команда NOP (“пустая” команда), которая не вызывает выполнения каких-либо операций, служит для реализации программных задержек или заполнения пропусков, образовавшихся в программе.

Специальные команды CLI, STI запрещают и разрешают обслуживание запросов прерывания. В процессорах Pentium для этого используется бит управления (флаг) IF в регистре EFLAGS .

Многие современные микропроцессоры выполняют команду идентификации, которая позволяет пользователю или другим устройствам получить информацию о типе процессора, используемого в данной системе. В процессорах Pentuim для этого служит команда CPUID , при выполнении которой необходимые данные о процессоре поступают в регистры EAX , EBX , ECX , EDX и могут затем считываться пользователем или операционной системой.

В зависимости от реализуемых процессором режимов работы и заданных типов обрабатываемых данных набор выполняемых команд может существенно расширяться.

Некоторые процессоры производят арифметические операции с двоично-десятичными числами или выполняют специальные команды коррекции результата при обработке таких чисел. В состав многих высокопроизводительных процессоров входит FPU - блок обработки чисел c “плавающей точкой”.

В ряде современных процессоров реализована групповая обработка нескольких целых чисел или чисел c “плавающей точкой” с помощью одной команды по принципу SIMD (“ Single Instruction – Multiple Data ”) - «Одна команда – Множество данных». Одновременное выполнение операций над несколькими операндами существенно повышает производительность процессора при работе с видео- и аудиоданными. Такие операции широко используются для обработки изображений, звуковых сигналов и в других приложениях. Для выполнения этих операций в состав процессоров введены специальные блоки, реализующие соответствующие наборы команд, которые в различных типах процессоров (Pentium , Athlon ) получили название MMX (“ Milti - Media Extension ”) – Мультимедийное Расширение, SSE (“ Streaming SIMD Extension ”) – Потоковое SIMD – расширение, “3 D Extension – Трехмерное Расширение.

Характерной особенностью процессоров компании Intel , начиная с модели 80286, является приоритетный контроль при обращении к памяти, который обеспечивается при работе процессора в режиме защищенных виртуальных адресов – “ Protected Mode ” (защищенный режим). Для реализации этого режима используется специальные группы команд, которые служат для организации защиты памяти в соответствии с принятым алгоритмом приоритетного обращения.

Введение.

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

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

При интерпретации каждая строка текста исходной программы анализируется (интерпретируется) и указанная в ней команда сразу выполняется. Реализация такого способа возлагается на программу–интерпретатор. Интерпретация занима-ет длительное время. Для повышения ее эффективности вместо обработки каждой строки интерпретатор предварительно осуществляет преобразование всех ко-мандных строк в символы (

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

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

Особенности языка.

Основные особенности ассемблера:

● вместо двоичных кодов в языке используются символьные имена - мнемо-ника. Например, для команды сложения (

) используется мнемоника

Вычитания (

умножения (

Деления (

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

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

● язык обеспечивает доступ ко всем объектам и командам. Языки высокого уровня такой способностью не обладают. Например, язык ассемблера позво-ляет выполнить проверку бита регистра флагов, а язык высокого уровня (на-пример,

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

● язык ассемблера не является универсальным языком. Для каждой определен-ной группы микропроцессоров имеется свой ассемблер. Языки высокого уровня лишены этого недостатка.

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

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

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

В большинстве программ лишь небольшой процент всего кода отвечает за большой процент времени выполнения программы. Обычно 1% программы отве-чает за 50% времени выполнения, а 10% программы отвечает за 90% времени выполнения. Поэтому для написания конкретной программы в реальных ус-ловиях используется как ассемблер, так и один из языков высокого уровня.

Формат оператора в языке ассемблера.

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

Поле метки.

Для поля метки отводится колонка 1. Метка является символи-ческим именем, или идентификатором, адреса памяти. Она необходима для того, чтобы можно было:

● совершить условный или безусловный переход к команде;

● получить доступ к месту, где хранятся данные.

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

В некоторых версиях языка ассемблера двоеточия ставятся только после ме-ток команд, но не после меток данных, а длина метки может быть ограничена 6 или 8 символами.

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

Поле кода операции.

Это поле содержит мнемокод команды или псевдо-команды (см. ниже). Мнемокод команд выбирается разработчиками языка. В язы-ке ассемблера

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

), а для сохранения содержимого регистра в памяти - мнемоника

). В языках ассемблера

для обеих операций можно ис-пользовать одно имя, соответственно

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

Мнемоника регистров также зависит от версии ассемблера (табл. 5.2.1).

Поле операнда.

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

● числовые данные,

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

Соответственно двоичная, восьмеричная, шестнадцатеричная, десятичная системы счисления (

можно не записывать). Если первой цифрой шестнадцатеричного числа являются А, В, С,

То впереди добавляется незначащий 0 (нуль);

● коды внутренних регистров микропроцессора и ячейки памяти

М (источников или приемников информации) в виде букв А, В, С,

М или их адреса в любой системе счисления (например, 10В - адрес регистра

в двоичной системе);

● идентификаторы,

для регистровых пар ВС,

Первые буквы В,

Н; для пары аккумулятора и регистра признаков -

; для счетчика команд -

;для указателя стека -

● метки, указывающие адреса операндов или следующих команд в условных

(при выполнении условия) и безусловных переходах. Например, операнд М1 в команде

означает необходимость безусловного перехода к коман-де, адрес которой в поле метки отмечен идентификатором М1;

● выражения,

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

Определить слово), а позднее ввели альтернативный вариант.

который с самого начала был в языке для процессоров

В версии языка

используется

Определить константу).

Процессоры обрабатывают операнды разной длины. Для ее определения раз-работчики ассемблера приняли разные решения, например:

II регистры разной длины имеют разные названия: ЕАХ - для раз-мещения 32–битных операндов (тип

); АХ - для 16–битных (тип

и АН - для 8–битных (тип

● для процессоров

к каждому коду операции прибавляются суффиксы: суффикс

Для типа

; суффикс «.В» для типа

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

) и слова в 64–битный ре-гистр используются коды операций

соответственно.

Поле комментариев.

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

● точка с запятой (;) в языках для процессоров фирмы

● восклицательный знак (!) в языках для

Каждая отдельная строка, отведенная под комментарий, предваряется начальным символом.

Псевдокоманды (директивы).

В языке ассемблера можно выделить два ос-новных вида команд:

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

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

для семейства

.

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

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

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

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

Макрос, или макрокоманда, характеризуется тремя аспектами: макроопреде-лением, макрообращением и макрорасширением.

Макроопределение

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

Макроопределение имеет следующую структуру:

Список выражений; Макроопределение

В приведенной структуре макроопределения можно выделить три части:

● заголовок

макроса, включающий в себя имя

Псевдокоманду

и набор параметров;

● отмеченное точками тело макроса;

● команда

окончания

макроопределения.

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

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

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

Когда в процессе компиляции ассемблер встречает макроопределение, он со-храняет его в таблице макроопределений. При последующих появлениях в про-грамме имени (

) макроса ассемблер замещает его телом макроса.

Использование имени макроса в качестве кода операции называется макро–обращением (макровызовом), а его замещение телом макроса - макрорасши-рением.

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

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

Процесс ассемблирования осуществляется в два прохода:

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

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

Макросы с параметрами.

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

● с фактическими параметрами, которые помещаются в поле операндов макро-обращения;

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

использования макросов с параметрами.

В программе 1 приведено две похожих последовательности команд, отличающихся тем, что пер-вая из них меняет местами Р и

А вторая

В программе 2 включен макрос с двумя формальными параметрами Р1 и Р2. Во время расшире-ния макроса каждый символ Р1 внутри тела макроса замещается первым фактическим параметром (Р,

), а символ Р2 замещается вторым фактическим параметром (

) из программы № 1. В макровызо-ве

программы 2 обозначено: Р,

Первый фактический параметр,

Второй фактический параметр.

Программа 1

Программа 2

MOV EBX,Q MOV EAX,Pl

MOV Q,EAX MOV EBX,P2

MOV P,EBX MOV P2,EAX

Расширенные возможности.

Рассмотрим некоторые расширенные возмож-ности языка

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

метка объявляется локальной (

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

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

IF WORDSIZE GT 16 M2 MACRO

Макрос М2 может быть определен в обеих частях оператора

Однако опре-деление зависит от того, на каком процессоре ассемблируется программа: на 16–битном или на 32–битном. Если М1 не вызывается, то макрос М2 вообще не будет определен.

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

Об использовании макросредств в ассемблере.

При использовании мак-росов ассемблер должен уметь выполнять две функции: сохранять макроопреде-ления и расширять макровызовы.

Сохранение макроопределений.

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

При встрече с макросом в процессе ассемблирования создается:

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

● список формальных параметров.

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

Внутреннее представление макроса

из приведенного выше примера для программы 2 (стр. 244) имеет вид:

MOV EAX,&P1; MOV EBX,&P2; MOV &P2EAX;MOV &

где в качестве символа возврата каретки используется точка с запятой, а в каче-стве символа формального параметра - амперсант &.

Расширение макровызовов.

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

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

Двухпроходной ассемблер.

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

● транслировать его на машинный язык;

● перенести полученный машинный код в файл, а соответствующую часть лис-тинга - в другой файл;

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

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

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

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

Первый проход.

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

;Значение - размер буфера

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

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

Таблица символьных имен

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

● длину поля данных, связанного с символом;

● биты перераспределения памяти (которые показывают, изменяется ли зна-чение символа, если программа загружается не в том адресе, в котором предполагал ассемблер);

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

Символьные имена являются метками. Они могут быть заданы с помощью операторов (например,

Таблица директив.

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

Таблица кодов операций.

Для каждого кода операции в таблице преду-смотрены отдельные графы: обозначение кода операции, операнд 1, операнд 2, 16–ричное значение кода операции, длина команды и тип команды (табл. 5.2.5). Коды операций делятся на группы в зависимости от числа и вида операндов. Тип команды определяет номер группы и задает процедуру, которая вызывается для обработки всех команд данной группы.

Второй проход.

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

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

Исходная программа может содержать ошибки, например:

приведенный символ не определен или определен более одного раза;

● код операции представлен недопустимым именем (из–за опечатки), не снабжен достаточным количеством операндов или имеет слишком много операндов;

● отсутствует оператор

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

Статьи посвященной языку ассемблер.

Общие сведения о языке ассемблера

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

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

Символические имена, вводимые при программировании на языке ассемблера, как правило отражают семантику программы, а аббревиатура команд - их основную функцию. Например: PARAM - параметр, TABLE - таблица, MASK - маска, ADD - сложение, SUB - вычитание и т.д. п. Такие имена легко запоминаются программистом.

Для программирования на языке ассемблера необходимо иметь сложные инструментальные средства, чем при программировании на машинном языке: нужны вычислительные комплексы на базе микро - ЭВМ или ПЭВМ с комплектом периферийных устройств (алфавитно-цифровая клавиатура, символьный дисплей, НГМД и печатающее устройство), а также резидентные или кросс-системы программирования для необходимых типов микропроцессоров. Язык ассемблера позволяет эффективно писать и отлаживать значительно более сложные программы, чем машинный язык (до 1 - 4 Кбайт).

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

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

В связи с этим практически все программы управления устройствами ввода/вывода (драйверы) пишутся на языке ассемблера не смотря на наличие достаточно большой номенклатуры языков высокого уровня.

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

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

стандартный формат для строк программы, описываемой на ассемблере;

формат для указания различных способов адресации и вариантов команд;

формат для указания символьных констант и констант целочисленного типа в различных системах счисления;

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

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

Для микро - ЭВМ, построенных на базе наиболее распространенных типов микропроцессоров, может существовать несколько вариантов языка ассемблера, однако практическое распространение обычно имеет один - это так называемый стандартный язык ассемблера

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

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

· операционной - определяющей, "что делать";

· операндной - определяющей объекты обработки, "с чем делать".

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

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

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

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

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

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

Прямая адресация : эффективный адрес определяется непосредственно полем смещения машинной команды, которое может иметь размер 8, 16 или 32 бита.

mov eax, sum ; eax = sum

Ассемблер заменяет sum на соответствующий адрес, хранящийся в сегменте данных (по умолчанию адресуется регистром ds) и значение, хранящееся по адресу sum, помещает в регистр eax.

Косвенная адресация в свою очередь имеет следующие виды:

· косвенная базовая (регистровая) адресация;

· косвенная базовая (регистровая) адресация со смещением;

· косвенная индексная адресация;

· косвенная базовая индексная адресация.

Косвенная базовая (регистровая) адресация. При такой адресации эффективный адрес операнда может находиться в любом из регистров общего назначения, кроме sp/esp и bp/ebp (это специфические регистры для работы с сегментом стека). Синтаксически в команде этот режим адресации выражается заключением имени регистра в квадратные скобки .

mov eax, ; eax = *esi; *esi значение по адресу esi