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


Мы поможем в написании ваших работ!



ЗНАЕТЕ ЛИ ВЫ?

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



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

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

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

[метка:] <мнемоника_команды> [операнд1][,операнд2][,операнд3] [;комментарии]

Обязательным является только <мнемоника_команды>.

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

Поле <мнемоники_команды> содержит имя команды процессора (например, MOV, ADD).

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

Поле комментариев начинается с символа ‘; ’ и может содержать любые символы. Транслятор просто игнорирует все символы, которые идут после точки с запятой. Комментарии могут быть самостоятельными, т.е. не входить в команду ассемблера. Для этого достаточно начать строку с точки с запятой.

Пример строки программы из четырех полей:

Поле метки   Поле операции Поле операндов Поле комментария
M1: Add AX, BX ; сложение

 

Имена данных, процедур, сегментов или метки команд могут состоять не более чем из 31 латинских букв (A Z, az) и цифр (от 0 до 9), причем первым символом должна быть обязательно буква. Большие и маленькие буквы не различаются. При написании текста программ могут использоваться знаки ?, @, $, _, & и разделители ,. [ ] () < > { } + / * %! ' "? \ = # ^.

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

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

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

Команда может иметь один или два операнда, или вообще быть без операндов. Рассмотрим следующие три примера:

  Команда Операнд Комментарий
Нет операндов RET   ;Вернуться
Один операнд INC CX ;Увеличить CX
Два операнда ADD AX,12 ;Прибавить 12 к AX

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

 

MOV AX,BX      ;Переслать содержимое BX в регистр AX

MOV AX,WORDA             ;Переслать содержимое WORDA в регистр AX

MOV AX,[BX]     ;Переслать содержимое памяти с адресом,

                                     ; хранящимся в регистре BX, в регистр AX

MOV AX,25                      ;Переслать значение 25 в регистр AX

MOV AX,[25]      ;Переслать содержимое по смещению 25

 

Основные типы операндов

· Постоянные или непосредственные операнды — число, строка, имя или выражение, имеющие некоторое фиксированное значение. Имя не должно быть перемещаемым, то есть зависеть от адреса загрузки программы в память. К примеру, оно может быть определено операторами equ или =.

num equ 5 imd = num-2        mov al,num                   ;эквивалентно mov al,5                                   ;5 здесь непосредственный операнд       add [si],imd     ; imd= 3 - непосредственный операнд       mov al,5           ;5 - непосредственный операнд

· Адресные операнды — задают физическое расположение операнда в памяти с помощью указания двух составляющих адреса: сегмента и смещения

   mov ax,0000h        mov ds,ax            ; ds – регистр сегмента данных       mov ax,ds:0000h;записать слово в ax из области памяти                                           ; по физическому адресу 0000:0000

Счетчик адреса — специфический вид операнда. Он обозначается знаком $. Транслятор подставляет вместо него текущее значение счетчика адреса.

       jmp $+ 3          ; безусловный переход на команду mov                                      ; команда jmp занимает 2 байта.       cld                                     ; длина команды cld составляет 1 байт       mov al,1

· Регистровый операнд — это просто имя регистра. В программе на ассемблере можно использовать имена всех регистров общего назначения и большинства системных регистров.

  mov al ,4            ;константу 4 заносим в регистр al        mov dl,pass +4   ;байт по адресу pass +4 в регистр dl       add al,dl           ;команда с регистровыми операндами

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

Типы операторов

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

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

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

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

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

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

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

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

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

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

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

Краткая характеристика операторов:

· Арифметические операторы. К ним относятся: унарные «+» и «–», бинарные «+» и «–», умножения «*», целочисленного деления «/», получения остатка от деления «mod».

Эти операторы расположены на уровнях приоритета 6, 7, 8,

tab_size       equ 50  ;размер массива в байтах size_el equ 2                ;размер элементов;вычисляется число элементов массива и заносится в регистр cx                   mov cx,tab_size / size_el ;оператор «/»

· Операторы сдвига выполняют сдвиг выражения на указанное количество разрядов

  mask_b equ 10111011  ;исходное состояние маски                   mov al,mask_b shr 3;al =00010111

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

flags            equ   10010011                   mov al,flags xor 01h;al =10010010      ;пересылка в al поля flags с инвертированным правым битом                                                                               

· Индексный оператор [ ] - транслятор их наличие воспринимает как указание сложить значение выражение_1 за этими скобками с выражение_2, заключенным в скобки (< выражение_1 >[< выражение_2> ]).

  m ov ax, mas[si];пересылка слова по адресу mas+(si) в регистр ax

· Оператор получения смещения выражения offset позволяет получить значение смещения выражения в байтах относительно начала того сегмента, в котором выражение определено

.data           ;сегмент данных pole             dw  5....code       ;сегмент программы... mov ax, seg pole mov es, ax

· Операторы сравнения (возвращают значение “истина” или “ложь”) предназначены для формирования логических выражений. Логическое значение “истина” соответствует цифровой единице, а “ложь” — нулю.

tab_size equ 30                   ;размер таблицы…        mov al,tab_size ge 50;загрузка размера таблицы в al cmp al, 0                 ;если tab_size < 50, то je m1;переход на m1m1:

Если значение tab_size больше или равно 50, то результат в al равен 0 ffh, а если tab_size меньше 50, то al равно 00 h. Команда cmp сравнивает значение al с нулем и устанавливает соответствующие флаги в flags/eflags. Команда je на основе анализа этих флагов передает или не передает управление на метку m 1.

CMP – сравнивает два операнда путем вычитания второго операнда из первого. Значения операндов при этом не меняются. Используется для дальнейшего анализа командой условного перехода.

1-ый операнд = Рг или переменная, 2-ой операнд = число, Рг или переменная (cmp ax,bx; cmp ax,3; cmp d,ax).

· Оператор переопределения типа ptr применяется для переопределения или уточнения типа метки или переменной, определяемых выражением. Тип может принимать одно из следующих значений: byte, word, dword, qword, tbyte, near, far.

d_wrd dd 0... mov al, byte ptr d _ wrd +1;пересылка второго байта из двойного слова

Переменная d_wrd имеет тип двойного слова. Если возникнет необходимость обращения не ко всей переменной, а только к одному из входящих в нее байтов (например, ко второму), то при использовании команды mov al,d_wrd+1 транслятор выдаст сообщение о несовпадении типов операндов. Оператор ptr позволяет непосредственно в команде переопределить тип и выполнить команду.

· Оператор переопределения сегмента: (двоеточие) заставляет вычислять физический адрес относительно конкретно задаваемой сегментной составляющей: «имя сегментного регистра», «имя сегмента» из соответствующей директивы SEGMENT или «имя группы». Микропроцессор на аппаратном уровне поддерживает три типа сегментов — кода, стека и данных. Для выборки на выполнение очередной команды микропроцессор должен обязательно посмотреть содержимое сегментного регистра cs и только его. В этом регистре содержится (пока еще не сдвинутый) физический адрес начала сегмента команд. Для получения адреса конкретной команды микропроцессору остается умножить содержимое cs на 16 (что означает сдвиг на четыре разряда) и сложить полученное 20-разрядное число с относительным (математическим) адресом.

Режимы адресации

1. Регистровая прямая - операнд находится в регистре.

Обозначение - <регистр>,

< регистр > - АХ, ВХ, СХ, DX, SI, DI, BP, SP, AL, BL, С L, DL, AH, BH, CH, DH.

mov АХ, SI; переслать содержимое регистра SI в регистр АХ.

2. Непосредственная -непосредственный операнд (константа) присутствует в команде.

Обозначение - < константное выражение >.

mov AX, 093 Ah; занести константу 093 Ah в регистр АХ.

3. Прямая - исполнительный адрес операнда присутствует в команде.

Обозначение - < переменная >+/-< константное выражение >.

mov AX, WW; переслать в АХ слово памяти с именем WW

mov BX, WW +2; переслать в ВХ слово памяти отстоящее от

                       ; переменной с именем WW на 2 байта.

4. Регистровая косвенная - регистр содержит адрес операнда.

Обозначение - [< регистр >],

< регистр > - ВХ, ВР, SI, DI.

mov [ BX ], CL; переслать содержимое регистра CL по адресу,

                     ; находящемуся в регистре ВХ.

5. Регистровая относительная - адрес операнда вычисляется как сумма содержимого регистра и смещения.

Обозначение - < переменная >[< регистр >] или [< регистр >]< кон­с­та­н­т­ное выражение >,

< регистр > - SI или DI индексная адресация, ВХ или ВР - базовая адресация.

mov АХ, WW [ SI ]; переслать в АХ слово из памяти, адрес которого

 ;вычисляется как сумма содержимого регистра SI и смещения WW.

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

Обозначение - [< базов. регистр>][< индексн. регистр>] или <переменная >[<базов. регистр >][< индекс. регистр >] или [<базов. регистр >][< индекс. регистр >]< константное выражение,

где < индекс. регистр > - SI или DI, < базов. Регистр > - ВХ или ВР.

mov [ BX + SI + 2], CL; переслать содержимое регистра CL по адресу, ­

; вычисляемому как сумма содержимого регистров ВХ, SI и константы 2.

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

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

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

5.5.1 Директива задания исходных данных:

[<имя>] d <тип> <константа>[,<константа>, <константа>,...]

· <имя> - имя массива данных, по которому к ним можно обратиться из команды;

· d (define)– определяет начало массива данных;

· <тип> - размер констант, входящих в массив:

b байт,
w слово (два байта),
d двойное слово,
q учетверённое слово,
t десять байтов;

· <константа> - числовой или символьный элемент массива дан­ных.

В ассемблере используется несколько типов констант:

десятичные  – последовательность цифр от 0 до 9;

шестнадцатеричные – последовательность шестнадцатеричных цифр от 0 до 9 и от А или а до F или f завершающаяся буквой H или h, первой должна быть десятичная цифра или 0;

восьмеричные – последовательность цифр от 0 до 7, завершающаяся буквами Q или q;

двоичные – последовательность цифр от 0 до 1, завершающаяся буквой B или b;

символьные – символ или группа символов, заключённые в кавычки.

· знак? – используется для резервирования места для данных.

Например,

data 1 db 123, 0 a 2 h, 75 q, 110011 b, ' a ', 'пример',?,?

· Для заполнения больших массивов используется директива dup (duplicate):

<число повторений> dup (<образец>)

<число повторений> - задаёт количество размещаемых в памяти данных, определяемых образцом;

<образец> - любая допустимая группа констант.

Например,

data 2 db 23 dup (1, 2, ' x ')

выделяет в памяти 23 · 3 = 69 байтов и заносит в них образец 1, 2, ' x ', 1, 2, ' x ', ….

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

assume <имя сегментного регистра>: <имя сегмента или nothing >[, <имя сегментного регистра>: <имя сегмента или nothing >, …]

Для задания адреса в памяти требуется два регистра, один из них всегда сегментный, поэтому в команде при обращении к памяти приходиться набирать имя сегментного регистра, часто одного и того же. Директива assume позволяет избежать этого. Транслятор сопоставляет имя массива данных и автоматически подставляет сегментный регистр, заданный для сегмента, в котором расположен данный массив. Слово nothing показывает, что данный сегментный регистр не адресуется по умолчанию. Директива assume может использоваться в программе при каждом изменении сегмента для данного сегментного регистра, но обязательно в начале сегмента, где она задаёт по умолчанию сегментный регистр для сегмента кодов.

Например,

assume cs:code, ds:data1, es:nothing

Здесь code и data1 – имена сегментов кодов и данных, соответственно.

Для простых программ, содержащих по одному сегменту для кода, данных и стека в трансляторы MASM и TASM ввели возможность использования упрощенных директив сегментации. Но здесь возникла проблема, связанная с тем, что необходимо было как-то компенсировать невозможность напрямую управлять размещением и комбинированием сегментов. Для этого совместно с упрощенными директивами сегментации стали использовать директиву указания модели памяти MODEL, которая частично стала управлять размещением сегментов и выполнять функции директивы ASSUME (поэтому при использовании упрощенных директив сегментации директиву ASSUME можно не использовать). Эта директива связывает сегменты, которые в случае использования упрощенных директив сегментации имеют предопределенные имена, с сегментными регистрами (хотя явно инициализировать ds все равно придется).

 Использование упрощенных директив сегментации .model small ;модель памяти .data                                ;сегмент данных message db   'Введите две шестнадцатеричные цифры,$' .stack                                   ;сегмент стека       db   256dup ('?');сегмент стека .code           ;сегмент кода main :          ;начало процедуры main        mov ax,@data  ;заносим адрес сегмента данных в регистр ax        mov ds,ax       ;ax в ds ;далее текст программы       mov ax,4c00h     ;пересылка имени DOS компоненты (4c00h)                                               ; в регистр ax        int   21h       ;вызов прерывания с номером 21h end  main                        ;конец программы с точкой входа main

Обязательным параметром директивы MODEL является модель памяти. Этот параметр определяет модель сегментации памяти для программного модуля. Предполагается, что программный модуль может иметь только определенные типы сегментов, которые определяются упомянутыми ранее упрощенными директивами описания сегментов (табл.5.1).

Таблица 5.1 Упрощенные директивы определения сегментов

Формат директивы Назначение
. CODE [имя] Начало или продолжение сегмента кода
. DATA Начало или продолжение сегмента инициализированных данных. Также используется для определения данных типа near
. CONS T Начало или продолжение сегмента постоянных данных (констант) модуля
. DATA? Начало или продолжение сегмента неинициализированных данных. Также используется для определения данных типа near
. STACK [размер] Начало или продолжение сегмента стека модуля. Параметр [размер] задает размер стека
. FARDATA [имя] Начало или продолжение сегмента инициализированных данных типа far
. FARDATA? [имя] Начало или продолжение сегмента неинициализированных данных типа far

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

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

Таблица 5.2 Идентификаторы, создаваемые директивой MODEL

Имя идентификатора Значение переменной
@code Физический адрес сегмента кода
@data Физический адрес сегмента данных типа near
@fardata Физический адрес сегмента данных типа far
@fardata? Физический адрес сегмента неинициализированных данных типа far
@stack Физический адрес сегмента стека

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

 Таблица 5.3 Модели памяти



Поделиться:


Последнее изменение этой страницы: 2021-12-15; просмотров: 50; Нарушение авторского права страницы; Мы поможем в написании вашей работы!

infopedia.su Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав. Обратная связь - 3.145.191.22 (0.048 с.)