4495

Массивы на языке ассемблера

Лекция

Информатика, кибернетика и программирование

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

Русский

2012-11-21

35.65 KB

137 чел.

Массивы на языке ассемблера

Дадим формальное определение:

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

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

  1.  Как описать массив в программе?
  2.  Как инициализировать массив, то есть как задать начальные значения его элементов?
  3.  Как организовать доступ к элементам массива?
  4.  Как организовать массивы с размерностью более одной?
  5.  Как организовать выполнение типовых операций с массивами?

Описание и инициализация массива в программе

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

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

 ;массив из 5 элементов.Размер каждого элемента 4 байта:

mas dd 1,2,3,4,5

  1.  Используя оператор повторения dup. К примеру:

 

;массив из 5 нулевых элементов.

;Размер каждого элемента 2 байта:

mas dw 5 dup (0)

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

  1.  Используя директивы label и rept. Пара этих директив может облегчить описание больших массивов в памяти и повысить наглядность такого описания. Директива rept относится к макросредствам языка ассемблера и вызывает повторение указанное число раз строк, заключенных между директивой и строкой endm. К примеру, определим массив байт в области памяти, обозначенной идентификатором mas_b. В данном случае директива label определяет символическое имя mas_b, аналогично тому, как это делают директивы резервирования и инициализации памяти. Достоинство директивы label в том, что она не резервирует память, а лишь определяет характеристики объекта. В данном случае объект — это ячейка памяти. Используя несколько директив label, записанных одна за другой, можно присвоить одной и той же области памяти разные имена и разный тип, что и сделано в следующем фрагменте:

 

...

n=0

...

mas_b label byte

mas_w label word

rept 4

dw 0f1f0h

endm

В результате в памяти будет создана последовательность из четырех слов f1f0. Эту последовательность можно трактовать как массив байт или слов в зависимости от того, какое имя области мы будем использовать в программе — mas_b или mas_w.

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

 

Листинг 2 Инициализация массива в цикле

;prg_12_1.asm

MASM

MODEL small

STACK 256

.data

mes db 0ah,0dh,'Массив- ','$'

mas db 10 dup (?) ;исходный массив

i db 0

.code

main:

mov ax,@data

mov ds,ax

xor ax,ax ;обнуление ax

mov cx,10 ;значение счетчика цикла в cx

mov si,0 ;индекс начального элемента в cx

go:    ;цикл инициализации

mov bh,i ;i в bh

mov mas[si],bh ;запись в массив i

inc i  ;инкремент i

inc si  ;продвижение к следующему элементу массива

loop go ;повторить цикл

;вывод на экран получившегося массива

 mov cx,10

mov si,0

mov ah,09h

lea dx,mes

int 21h

show:

 mov ah,02h ;функция вывода значения из al на экран

mov dl,mas[si]

add dl,30h ;преобразование числа в символ

 int 21h

inc si

loop show

exit:

mov ax,4c00h ;стандартный выход

int 21h

end main  ;конец программы

Доступ к элементам массива

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

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

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

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

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

mas dw 0,1,2,3,4,5

Пусть эта последовательность чисел трактуется как одномерный массив. Размерность каждого элемента определяется директивой dw, то есть она равна 2 байта. Чтобы получить доступ к третьему элементу, нужно к адресу массива прибавить 6. Нумерация элементов массива в ассемблере начинается с нуля.

То есть в нашем случае речь, фактически, идет о 4-м элементе массива — 3, но об этом знает только программист; микропроцессору в данном случае все равно — ему нужен только адрес.

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

база + (индекс*размер элемента) 

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

  1.  индексная адресация со смещением — режим адресации, при котором эффективный адрес формируется из двух компонентов:
  2.  постоянного (базового) — указанием прямого адреса массива в виде имени идентификатора, обозначающего начало массива;
  3.  переменного (индексного) — указанием имени индексного регистра.
  4.  К примеру:

mas dw 0,1,2,3,4,5

...

mov si,4

;поместить 3-й элемент массива mas в регистр ax:

mov ax,mas[si]

  1.  базовая индексная адресация со смещением — режим адресации, при котором эффективный адрес формируется максимум из трех компонентов:
  2.  постоянного (необязательный компонент), в качестве которой может выступать прямой адрес массива в виде имени идентификатора, обозначающего начало массива, или непосредственное значение;
  3.  переменного (базового) — указанием имени базового регистра;
  4.  переменного (индексного) — указанием имени индексного регистра.

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

Напомним, что в качестве базового регистра может использоваться любой из восьми регистров общего назначения. В качестве индексного регистра также можно использовать любой регистр общего назначения, за исключением esp/sp.

Микропроцессор позволяет масштабировать индекс. Это означает, что если указать после имени индексного регистра знак умножения “*” с последующей цифрой 2, 4 или 8, то содержимое индексного регистра будет умножаться на 2, 4 или 8, то есть масштабироваться.

Применение масштабирования облегчает работу с массивами, которые имеют размер элементов, равный 2, 4 или 8 байт, так как микропроцессор сам производит коррекцию индекса для получения адреса очередного элемента массива. Нам нужно лишь загрузить в индексный регистр значение требуемого индекса (считая от 0). Кстати сказать, возможность масштабирования появилась в микропроцессорах Intel, начиная с модели i486. По этой причине в рассматриваемом здесь примере программы стоит директива .486. Ее назначение, как и ранее использовавшейся директивы .386, в том, чтобы указать ассемблеру при формировании машинных команд на необходимость учета и использования дополнительных возможностей системы команд новых моделей микропроцессоров.

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

Листинг 3. Просмотр массива слов с использованием

масштабирования

;prg_12_2.asm

MASM

MODEL small

STACK 256

.data ;начало сегмента данных

;тексты сообщений:

mes1 db 'не равен 0!$',0ah,0dh

mes2 db 'равен 0!$',0ah,0dh

mes3 db 0ah,0dh,'Элемент $'

mas dw 2,7,0,0,1,9,3,6,0,8 ;исходный массив

.code

.486  ;это обязательно

main:

mov ax,@data

mov ds,ax ;связка ds с сегментом данных

 xor ax,ax ;обнуление ax

prepare:

 mov cx,10 ;значение счетчика цикла в cx

 mov esi,0 ;индекс в esi

compare:

 mov dx,mas[esi*2] ;первый элемент массива в dx

cmp dx,0 ;сравнение dx c 0

je equal ;переход, если равно

not_equal:  ;не равно

mov ah,09h ;вывод сообщения на экран

lea dx,mes3

int 21h

mov ah,02h ;вывод номера элемента массива на экран

 mov dx,si

add dl,30h

int 21h

mov ah,09h

lea dx,mes1

 int 21h

inc esi  ;на следующий элемент

dec cx  ;условие для выхода из цикла

jcxz exit ;cx=0? Если да — на выход

jmp compare ;нет — повторить цикл

equal:   ;равно 0

mov ah,09h ;вывод сообщения mes3 на экран

 lea dx,mes3

int 21h

mov ah,02h

mov dx,si

add dl,30h

 int 21h

mov ah,09h ;вывод сообщения mes2 на экран

lea dx,mes2

int 21h

inc esi  ;на следующий элемент

dec cx  ;все элементы обработаны?

 jcxz exit

jmp compare

exit:

 mov ax,4c00h ;стандартный выход

int 21h

end main ;конец программы

Еще несколько слов о соглашениях:

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

;переслать байт из области данных, адрес

которой находится в регистре ebx:

mov al,[ebx]

 

  1.  Если для задания адреса в команде используется прямая адресация (в виде идентификатора) в сочетании с одним регистром, то речь идет об индексной адресации. Регистр считается индексным, и поэтому можно использовать масштабирование для получения адреса нужного элемента массива:

add eax,mas[ebx*4]

;сложить содержимое eax с двойным словом в памяти

;по адресу mas + (ebx)*4

 

  1.  Если для описания адреса используются два регистра, то речь идет о базово-индексной адресации. Левый регистр рассматривается как базовый, а правый — как индексный. В общем случае это не принципиально, но если мы используем масштабирование с одним из регистров, то он всегда является индексным. Но лучше придерживаться определенных соглашений.
  2.  Помните, что применение регистров ebp/bp и esp/sp по умолчанию подразумевает, что сегментная составляющая адреса находится в регистре ss.

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

К примеру:

 mov ax,mas[ebx][ecx*2]

;адрес операнда равен [mas+(ebx)+(ecx)*2]

...

sub dx,[ebx+8][ecx*4]

;адрес операнда равен [(ebx)+8+(ecx)*4]

 

Но имейте в виду, что масштабирование эффективно лишь тогда, когда размерность элементов массива равна 2, 4 или 8 байт. Если же размерность элементов другая, то организовывать обращение к элементам массива нужно обычным способом, как описано ранее.

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

Листинг 4. Обработка массива элементов с нечетной длиной

;prg_11_3.asm

MASM

MODEL small ;модель памяти

STACK 256 ;размер стека

.data   ;начало сегмента данных

N=5    ;количество элементов массива

mas db 5 dup (3 dup (0))

.code   ;сегмент кода

main:   ;точка входа в программу

mov ax,@data

mov ds,ax

xor ax,ax ;обнуление ax

mov si,0 ;0 в si

 mov cx,N ;N в cx

go:

 mov dl,mas[si] ;первый байт поля в dl

inc dl   ;увеличение dl на 1 (по условию)

mov mas[si],dl ;заслать обратно в массив

add si,3 ;сдвиг на следующий элемент массива

loop go ;повтор цикла

mov si,0 ;подготовка к выводу на экран

mov cx,N

show:   ;вывод на экран содержимого

;первых байт полей

mov dl,mas[si]

 add dl,30h

mov ah,02h

int 21h

loop show

exit:

 mov ax,4c00h ;стандартный выход

int 21h

end main   ;конец программы


 

А также другие работы, которые могут Вас заинтересовать

11610. Работа с таблицами в MS Word’2000/2003 116.5 KB
  Лабораторная работа № 5 Тема: Работа с таблицами в MS Word2000/2003. Цель работы: Освоить основные приемы создания редактирования и форматирования таблиц в документах текстового процессора MS Word2000/2003. Содержание работы: Создать таблицу Отчетная ведомость по компью
11611. Графические возможности MS Word’2000/2003 139 KB
  Лабораторная работа № 6 Тема: Графические возможности MS Word2000/2003.. Цель работы: Освоить основные приемы создания редактирования и форматирования графических объектов в документах текстового процессора MS Word2000/2003. Содержание работы: Задание: Создать бланк фирмы п...
11612. Оформление математических формул в документах MS Word’2000/2003 99 KB
  Лабораторная работа № 7 Тема: Оформление математических формул в документах MS Word2000/2003. Цель работы: Освоить основные приемы создания и форматирования математических формул в текстовых документах MS Word2000/2003. Содержание работы: Освоение...
11613. Работа с большим (структурированным) документом MS Word’2000/2003 138.5 KB
  Лабораторная работа № 8 Тема: Работа с большим структурированным документом MS Word2000/2003 Цель работы: Освоить основные приемы оформления структурированного документа в MS Word2000/2003. Содержание работы: Создание структурированного документа. Оформление структ
11614. Решение задач в MatLab 324.86 KB
  Лабораторная работа №2. Решение задач в MatLab Цель лабораторной работы закрепление практических навыков решения задач в среде математического пакета MatLab необходимых для выполнения лабораторных работ по дисциплине ТИПиС. Этап I. Решение уравнений в пакете MatLa...
11615. Создание собственных функций на MatLa 147.39 KB
  Создание собственных функций Необходимо создать программу на MatLab. При этом все операции с матрицами должны производиться без использования стандартных функций. Создание функции сложения матриц: function C=addmAB d1=sizeA; d2=sizeB; if d11==d21||d12==d22 n=d11; m=d12; ...
11616. ПЕРЕХОДНЫЕ ПРОЦЕССЫ В ЛИНЕЙНЫХ ЭЛЕКТРИЧЕСКИХ ЦЕПЯХ С СОСРЕДОТОЧЕННЫМИ ПАРАМЕТРАМИ 2.14 MB
  Лабораторная работа №7 ПЕРЕХОДНЫЕ ПРОЦЕССЫ В ЛИНЕЙНЫХ ЭЛЕКТРИЧЕСКИХ ЦЕПЯХ С СОСРЕДОТОЧЕННЫМИ ПАРАМЕТРАМИ Целью работы является исследование переходных процессов в линейных электрических цепях содержащих сопротивления индуктивность и емкость при действии и...
11617. Изучение рентгеновских трубок и аппаратов 629.5 KB
  ЛАБОРАТОРНАЯ РАБОТА №1. Изучение рентгеновских трубок и аппаратов. РЕНТГЕНОВЧСКИЕ ТРУБКИ. Рентгеновская трубка является источником рентгеновских лучей возникающих в ней в результате взаимодействия быстро летящих электронов с атомами анода установленного...
11618. Мерология. Лабораторный практикум 1.36 MB
  Мерология. Лабораторный практикум Учебнометодическое пособие для студентов приборостроительного факультета Лабораторный практикум предназначен для использования в высших учебных заведениях при подготовке инженеров по специальности Метрология стандартизация и...